├── .coveragerc ├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── .gitmodules ├── .readthedocs.yaml ├── .requirements.txt ├── .travis.yml ├── LICENSE.md ├── MANIFEST.in ├── README.md ├── docs ├── Makefile ├── api.rst ├── changelog.rst ├── conf.py ├── conversion.rst ├── development.rst ├── index.rst ├── introduction.rst ├── sptk.rst ├── synthesis.rst └── util.rst ├── examples ├── Speech analysis and re-synthesis.ipynb └── pysptk introduction.ipynb ├── pyproject.toml ├── pysptk ├── __init__.py ├── _sptk.pxd ├── _sptk.pyx ├── conversion.py ├── example_audio_data │ ├── COPYING │ └── arctic_a0007.wav ├── sptk.py ├── synthesis.py └── util.py ├── release.sh ├── setup.cfg ├── setup.py ├── tests ├── data │ ├── arctic_a007_p16_L60_H240_o0_rapt.txt │ ├── arctic_a007_p16_L60_H240_o0_swipe.txt │ ├── test16k.cdist │ ├── test16k.cep │ ├── test16k.float │ ├── test16k.lpc │ ├── test16k.lsp │ ├── test16k.lsp2lpc │ ├── test16k.mcep.cep │ ├── test16k_57.mgc │ ├── test16k_57.sp │ ├── test16k_H.txt │ ├── test16k_mcep.txt │ ├── test16k_mcep_from_H.txt │ └── test16k_windowed.txt ├── regression │ ├── __init__.py │ ├── test_metrics.py │ └── test_mgcep.py ├── test_adaptive.py ├── test_conversions.py ├── test_f0.py ├── test_lib.py ├── test_mfcc.py ├── test_mgcep.py ├── test_sptk.py ├── test_synthesis.py ├── test_synthesis_filters.py ├── test_utils.py └── test_window.py └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | plugins = Cython.Coverage 3 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: Python package 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ${{ matrix.os }} 16 | strategy: 17 | matrix: 18 | include: 19 | - os: ubuntu-latest 20 | python-version: 3.8 21 | - os: ubuntu-latest 22 | python-version: 3.9 23 | - os: ubuntu-latest 24 | python-version: '3.10' 25 | - os: ubuntu-latest 26 | python-version: '3.11' 27 | - os: macos-latest 28 | python-version: 3.9 29 | - os: windows-latest 30 | python-version: 3.9 31 | 32 | steps: 33 | - uses: actions/checkout@v2 34 | with: 35 | submodules: true 36 | - name: Set up Python ${{ matrix.python-version }} 37 | uses: actions/setup-python@v4 38 | with: 39 | python-version: ${{ matrix.python-version }} 40 | - name: Install OS dependencies 41 | shell: bash -l {0} 42 | run: | 43 | case "${{ runner.os }}" in 44 | Linux) 45 | sudo apt-get install -yy libsamplerate0 libsndfile1 46 | ;; 47 | macOS) 48 | brew install libsamplerate 49 | ;; 50 | esac 51 | - name: Install dependencies 52 | run: | 53 | python -m pip install --upgrade pip 54 | pip install -e ".[test,lint]" 55 | - name: Lint with pysen 56 | run: | 57 | pysen run lint 58 | - name: Test 59 | run: | 60 | pytest --cov=pysptk --cov-report xml -v tests/ 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | pysptk/_sptk.c 2 | pysptk/version.py 3 | docs/generated 4 | docs/.doctrees 5 | docs/plot_directive 6 | *.raw 7 | 8 | # Created by https://www.gitignore.io 9 | 10 | ### Python ### 11 | # Byte-compiled / optimized / DLL files 12 | __pycache__/ 13 | *.py[cod] 14 | 15 | # C extensions 16 | *.so 17 | 18 | # Distribution / packaging 19 | .Python 20 | env/ 21 | build/ 22 | develop-eggs/ 23 | dist/ 24 | downloads/ 25 | eggs/ 26 | lib/ 27 | lib64/ 28 | parts/ 29 | sdist/ 30 | var/ 31 | *.egg-info/ 32 | .installed.cfg 33 | *.egg 34 | 35 | # PyInstaller 36 | # Usually these files are written by a python script from a template 37 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 38 | *.manifest 39 | *.spec 40 | 41 | # Installer logs 42 | pip-log.txt 43 | pip-delete-this-directory.txt 44 | 45 | # Unit test / coverage reports 46 | htmlcov/ 47 | .tox/ 48 | .coverage 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | 60 | # Sphinx documentation 61 | docs/_build/ 62 | 63 | # PyBuilder 64 | target/ 65 | 66 | 67 | ### IPythonNotebook ### 68 | # Temporary data 69 | .ipynb_checkpoints/ 70 | 71 | 72 | ### SublimeText ### 73 | # cache files for sublime text 74 | *.tmlanguage.cache 75 | *.tmPreferences.cache 76 | *.stTheme.cache 77 | 78 | # workspace files are user-specific 79 | *.sublime-workspace 80 | 81 | # project files should be checked into the repository, unless a significant 82 | # proportion of contributors will probably not be using SublimeText 83 | # *.sublime-project 84 | 85 | # sftp configuration file 86 | sftp-config.json 87 | 88 | 89 | ### Emacs ### 90 | # -*- mode: gitignore; -*- 91 | *~ 92 | \#*\# 93 | /.emacs.desktop 94 | /.emacs.desktop.lock 95 | *.elc 96 | auto-save-list 97 | tramp 98 | .\#* 99 | 100 | # Org-mode 101 | .org-id-locations 102 | *_archive 103 | 104 | # flymake-mode 105 | *_flymake.* 106 | 107 | # eshell files 108 | /eshell/history 109 | /eshell/lastdir 110 | 111 | # elpa packages 112 | /elpa/ 113 | 114 | # reftex files 115 | *.rel 116 | 117 | # AUCTeX auto folder 118 | /auto/ 119 | 120 | # cask packages 121 | .cask/ 122 | 123 | 124 | ### Vim ### 125 | [._]*.s[a-w][a-z] 126 | [._]s[a-w][a-z] 127 | *.un~ 128 | Session.vim 129 | .netrwhist 130 | *~ 131 | 132 | 133 | ### C++ ### 134 | # Compiled Object files 135 | *.slo 136 | *.lo 137 | *.o 138 | *.obj 139 | 140 | # Precompiled Headers 141 | *.gch 142 | *.pch 143 | 144 | # Compiled Dynamic libraries 145 | *.so 146 | *.dylib 147 | *.dll 148 | 149 | # Fortran module files 150 | *.mod 151 | 152 | # Compiled Static libraries 153 | *.lai 154 | *.la 155 | *.a 156 | *.lib 157 | 158 | # Executables 159 | *.exe 160 | *.out 161 | *.app 162 | 163 | 164 | ### OSX ### 165 | .DS_Store 166 | .AppleDouble 167 | .LSOverride 168 | 169 | # Icon must end with two \r 170 | Icon 171 | 172 | 173 | # Thumbnails 174 | ._* 175 | 176 | # Files that might appear on external disk 177 | .Spotlight-V100 178 | .Trashes 179 | 180 | # Directories potentially created on remote AFP share 181 | .AppleDB 182 | .AppleDesktop 183 | Network Trash Folder 184 | Temporary Items 185 | .apdisk 186 | 187 | 188 | ### Linux ### 189 | *~ 190 | 191 | # KDE directory preferences 192 | .directory 193 | 194 | # Linux trash folder which might appear on any partition or disk 195 | .Trash-* 196 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/SPTK"] 2 | path = lib/SPTK 3 | url = https://github.com/r9y9/SPTK.git 4 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the version of Python and other tools you might need 9 | build: 10 | os: ubuntu-20.04 11 | tools: 12 | python: "3.9" 13 | # You can also specify other tool versions: 14 | # nodejs: "16" 15 | # rust: "1.55" 16 | # golang: "1.17" 17 | apt_packages: 18 | - libsamplerate0 19 | - libsndfile1 20 | 21 | # Build documentation in the docs/ directory with Sphinx 22 | sphinx: 23 | configuration: docs/conf.py 24 | 25 | # If using Sphinx, optionally build your docs in additional formats such as PDF 26 | # formats: 27 | # - pdf 28 | 29 | # Optionally declare the Python requirements required to build your docs 30 | python: 31 | install: 32 | - requirements: .requirements.txt 33 | -------------------------------------------------------------------------------- /.requirements.txt: -------------------------------------------------------------------------------- 1 | numpy >= 1.20.0 2 | cython >= 0.21.0, <= 0.29.36 3 | numpydoc 4 | pysptk 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | python: 4 | - "3.8" 5 | 6 | notifications: 7 | email: false 8 | 9 | os: 10 | - linux 11 | 12 | before_install: 13 | - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules 14 | - git submodule update --init --recursive 15 | # anaconda 16 | - wget http://repo.continuum.io/miniconda/Miniconda3-3.8.3-Linux-x86_64.sh -O miniconda.sh 17 | - bash miniconda.sh -b -p $HOME/miniconda 18 | - export PATH="$HOME/miniconda/bin:$PATH" 19 | - hash -r 20 | - conda config --set always_yes yes --set changeps1 no 21 | - conda update -q conda 22 | # Useful for debugging any issues with conda 23 | - conda config --add channels pypi 24 | - conda info -a 25 | - conda create -q -n test-environment "python=$TRAVIS_PYTHON_VERSION" pip cython coverage coveralls 26 | - source activate test-environment 27 | 28 | install: 29 | - pip install -e ".[test]" 30 | 31 | script: 32 | - pytest --cov=pysptk --cov-report xml -v tests/ 33 | 34 | after_success: 35 | - coveralls 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The pysptk package is licensed under the MIT "Expat" License: 2 | 3 | > Copyright (c) 2015: Ryuichi Yamamoto. 4 | > 5 | > Permission is hereby granted, free of charge, to any person obtaining 6 | > a copy of this software and associated documentation files (the 7 | > "Software"), to deal in the Software without restriction, including 8 | > without limitation the rights to use, copy, modify, merge, publish, 9 | > distribute, sublicense, and/or sell copies of the Software, and to 10 | > permit persons to whom the Software is furnished to do so, subject to 11 | > the following conditions: 12 | > 13 | > The above copyright notice and this permission notice shall be 14 | > included in all copies or substantial portions of the Software. 15 | > 16 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | > IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | > CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | > TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | > SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include lib *.c *.h COPYING 2 | recursive-include pysptk *.c *.pxd *.pyx *.wav COPYING 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pysptk 2 | 3 | [![PyPI](https://img.shields.io/pypi/v/pysptk.svg)](https://pypi.python.org/pypi/pysptk) 4 | [![Python package](https://github.com/r9y9/pysptk/actions/workflows/ci.yaml/badge.svg)](https://github.com/r9y9/pysptk/actions/workflows/ci.yaml) 5 | [![Build Status](https://app.travis-ci.com/r9y9/pysptk.svg?branch=master)](https://app.travis-ci.com/r9y9/pysptk) 6 | [![Coverage Status](https://coveralls.io/repos/r9y9/pysptk/badge.svg?branch=master&service=github)](https://coveralls.io/github/r9y9/pysptk?branch=master) 7 | [![Documentation Status](https://readthedocs.org/projects/pysptk/badge/?version=latest)](https://readthedocs.org/projects/pysptk/?badge=latest) 8 | [![License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](LICENSE.md) 9 | [![][docs-stable-img]][docs-stable-url] 10 | [![][docs-latest-img]][docs-latest-url] 11 | [![DOI](https://zenodo.org/badge/41618046.svg)](https://zenodo.org/badge/latestdoi/41618046) 12 | 13 | A python wrapper for [Speech Signal Processing Toolkit (SPTK)](http://sp-tk.sourceforge.net/). 14 | 15 | **NOTE**: pysptk is based on a modified version of SPTK ([r9y9/SPTK](https://github.com/r9y9/SPTK)). 16 | 17 | ## Documentation 18 | 19 | - [**STABLE**][docs-stable-url] — **most recently tagged version of the documentation.** 20 | - [**LATEST**][docs-latest-url] — *in-development version of the documentation.* 21 | 22 | ## Demonstration notebook 23 | 24 | - [Introduction notebook](https://nbviewer.org/github/r9y9/pysptk/blob/master/examples/pysptk%20introduction.ipynb): a brief introduction to pysptk 25 | - [Speech analysis and re-synthesis](https://nbviewer.org/github/r9y9/pysptk/blob/master/examples/Speech%20analysis%20and%20re-synthesis.ipynb): a demonstration notebook for speech analysis and re-synthesis. Synthesized audio examples (English) are available on the notebook. 26 | 27 | ## Installation 28 | 29 | The latest release is availabe on pypi and you can install it by: 30 | 31 | ```bash 32 | pip install pysptk 33 | ``` 34 | 35 | If yout want the latest master, run 36 | 37 | ```bash 38 | pip install git+https://github.com/r9y9/pysptk 39 | ``` 40 | 41 | or clone the repository and then build it yourself. 42 | 43 | [docs-latest-img]: https://img.shields.io/badge/docs-latest-blue.svg 44 | [docs-latest-url]: https://pysptk.readthedocs.io/en/latest/ 45 | 46 | [docs-stable-img]: https://img.shields.io/badge/docs-stable-blue.svg 47 | [docs-stable-url]: https://pysptk.readthedocs.io/en/stable/ 48 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " applehelp to make an Apple Help Book" 34 | @echo " devhelp to make HTML files and a Devhelp project" 35 | @echo " epub to make an epub" 36 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 37 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 38 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 39 | @echo " text to make text files" 40 | @echo " man to make manual pages" 41 | @echo " texinfo to make Texinfo files" 42 | @echo " info to make Texinfo files and run them through makeinfo" 43 | @echo " gettext to make PO message catalogs" 44 | @echo " changes to make an overview of all changed/added/deprecated items" 45 | @echo " xml to make Docutils-native XML files" 46 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 47 | @echo " linkcheck to check all external links for integrity" 48 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 49 | @echo " coverage to run coverage check of the documentation (if enabled)" 50 | 51 | clean: 52 | rm -rf $(BUILDDIR)/* 53 | 54 | html: 55 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 56 | @echo 57 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 58 | 59 | dirhtml: 60 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 61 | @echo 62 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 63 | 64 | singlehtml: 65 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 66 | @echo 67 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 68 | 69 | pickle: 70 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 71 | @echo 72 | @echo "Build finished; now you can process the pickle files." 73 | 74 | json: 75 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 76 | @echo 77 | @echo "Build finished; now you can process the JSON files." 78 | 79 | htmlhelp: 80 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 81 | @echo 82 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 83 | ".hhp project file in $(BUILDDIR)/htmlhelp." 84 | 85 | qthelp: 86 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 87 | @echo 88 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 89 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 90 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pysptk.qhcp" 91 | @echo "To view the help file:" 92 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pysptk.qhc" 93 | 94 | applehelp: 95 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 96 | @echo 97 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 98 | @echo "N.B. You won't be able to view it unless you put it in" \ 99 | "~/Library/Documentation/Help or install it in your application" \ 100 | "bundle." 101 | 102 | devhelp: 103 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 104 | @echo 105 | @echo "Build finished." 106 | @echo "To view the help file:" 107 | @echo "# mkdir -p $$HOME/.local/share/devhelp/pysptk" 108 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pysptk" 109 | @echo "# devhelp" 110 | 111 | epub: 112 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 113 | @echo 114 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 115 | 116 | latex: 117 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 118 | @echo 119 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 120 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 121 | "(use \`make latexpdf' here to do that automatically)." 122 | 123 | latexpdf: 124 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 125 | @echo "Running LaTeX files through pdflatex..." 126 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 127 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 128 | 129 | latexpdfja: 130 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 131 | @echo "Running LaTeX files through platex and dvipdfmx..." 132 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 133 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 134 | 135 | text: 136 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 137 | @echo 138 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 139 | 140 | man: 141 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 142 | @echo 143 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 144 | 145 | texinfo: 146 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 147 | @echo 148 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 149 | @echo "Run \`make' in that directory to run these through makeinfo" \ 150 | "(use \`make info' here to do that automatically)." 151 | 152 | info: 153 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 154 | @echo "Running Texinfo files through makeinfo..." 155 | make -C $(BUILDDIR)/texinfo info 156 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 157 | 158 | gettext: 159 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 160 | @echo 161 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 162 | 163 | changes: 164 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 165 | @echo 166 | @echo "The overview file is in $(BUILDDIR)/changes." 167 | 168 | linkcheck: 169 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 170 | @echo 171 | @echo "Link check complete; look for any errors in the above output " \ 172 | "or in $(BUILDDIR)/linkcheck/output.txt." 173 | 174 | doctest: 175 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 176 | @echo "Testing of doctests in the sources finished, look at the " \ 177 | "results in $(BUILDDIR)/doctest/output.txt." 178 | 179 | coverage: 180 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 181 | @echo "Testing of coverage in the sources finished, look at the " \ 182 | "results in $(BUILDDIR)/coverage/python.txt." 183 | 184 | xml: 185 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 186 | @echo 187 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 188 | 189 | pseudoxml: 190 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 191 | @echo 192 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 193 | -------------------------------------------------------------------------------- /docs/api.rst: -------------------------------------------------------------------------------- 1 | API 2 | === 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | 7 | sptk 8 | conversion 9 | synthesis 10 | util 11 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | Change log 2 | ========== 3 | 4 | v0.2.1 <2023-07-20> 5 | -------------------- 6 | 7 | - `#96`_: Restrict Cython version to <3.0.0 8 | 9 | v0.2.0 <2022-11-06> 10 | -------------------- 11 | 12 | Newer numpy (>v1.20.0) is required to avoid ABI compatibility issues. Please check the updated installation guide. 13 | 14 | - `#92`_: Support for Python 3.10, rewrite tests with pytest 15 | 16 | v0.1.21 <2022-06-05> 17 | -------------------- 18 | 19 | Fixes windows build issues caused by intrinsic conflicts 20 | 21 | 22 | v0.1.20 <2022-01-04> 23 | -------------------- 24 | 25 | Fixes for ValueError: numpy.ndarray size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject 26 | 27 | v0.1.19 <2022-01-04> 28 | -------------------- 29 | 30 | - `#87`_: Add pysen and format all the codes. Appveyor is now disabled. Windows CI is done by Github Actions. 31 | - `#83`_: pitch: support automatic type converseion for swipe and rapt (API change) 32 | 33 | v0.1.18 <2020-03-02> 34 | -------------------- 35 | 36 | - `#75`_: Enable py38 test on travis 37 | - `#72`_: Fix itype!=0 for mgcep, gcep and related functions 38 | 39 | 40 | v0.1.17 <2019-05-31> 41 | -------------------- 42 | 43 | - Fixed python 3.7 installation problem 44 | 45 | v0.1.16 <2019-02-17> 46 | -------------------- 47 | 48 | - Fixed cython-generated files in the release tarball with latest numpy 49 | 50 | v0.1.15 <2019-01-08> 51 | -------------------- 52 | 53 | - `#65`_, #67`_: Should avoid build-time numpy dependency for newer releases 54 | 55 | v0.1.14 <2018-11-25> 56 | -------------------- 57 | 58 | - `#62`_, `#64`_: **IMPORTANT**: Add ``use_scipy`` option to ``levdur`` and ``lpc``, and set it to True by default to improve numerical stability. The results should be same regardless to the option, but this would be technically a breaking change. 59 | - `#64`_: Add ``acorr``. 60 | 61 | v0.1.13 <2018-11-19> 62 | -------------------- 63 | 64 | - Add All zero synthesis filter. 65 | - Add ``levdur``. 66 | - Add tranposed synthesis filters (``mlsadft``, ``poledft``, ``mglsadft``, ``glsadft``) 67 | - Add missing high level synthesis filter class ``GLSADF``. 68 | 69 | v0.1.12 <2018-10-27> 70 | -------------------- 71 | 72 | - `#63`_: Fix lpc2lsp bug, add lsp2lpc function. Add regression tests for those. 73 | 74 | v0.1.11 <2018-02-05> 75 | -------------------- 76 | 77 | - `#55`_: Add numpy implementation of cdist 78 | 79 | v0.1.10 <2018-01-02> 80 | -------------------- 81 | 82 | - `#54`_: Changes from SPTK v3.11 release. 6 and 7 pade approximatino in lmadf and mlsadf is now supported, 83 | 84 | v0.1.9 <2018-01-01> 85 | ------------------- 86 | 87 | - BUG fix: example_audio_data is now included in the release tar.gz 88 | 89 | 90 | v0.1.8 <2017-12-25> 91 | ------------------- 92 | 93 | - c2acr: Fix segfaults for small fftsize 94 | 95 | v0.1.7 <2017-06-28> 96 | ------------------- 97 | 98 | - Extend vec2vec functions to mat2mat 99 | `#49 `__ 100 | - Support automatic type conversions 101 | `#48 `__ 102 | 103 | v0.1.6 <2017-05-18> 104 | ------------------- 105 | 106 | - Add ``mcepalpha``. `#43 `__ 107 | - Add ``mc2e``. `#42 `__ 108 | - Add ``sp2mc`` and ``mc2sp``. 109 | `#41 `__ 110 | 111 | v0.1.5 <2017-04-22> 112 | ------------------- 113 | 114 | - Fix mcep eps check and input length 115 | `#39 `__ 116 | 117 | v0.1.4 <2015-11-23> 118 | ------------------- 119 | 120 | - Add developer documentation 121 | (`#34 `__) 122 | - Separate cython implementation and interface 123 | (`#35 `__) 124 | - Add RAPT (`#32 `__) 125 | - Add excite function 126 | (`#31 `__) 127 | `@jfsantos `__ 128 | - Fix inconsistent docs about normalization flag for window functions 129 | - Fix test failure in c2dps / ndps2c 130 | (`#29 `__) 131 | 132 | v0.1.3 <2015-10-02> 133 | ------------------- 134 | 135 | - Building binary wheels for Windows using Appveyor 136 | (`#28 `__) 137 | - Add Installation guide on windows 138 | (`#25 `__) 139 | - Start Windows continuous integration on AppVeyor 140 | (`#24 `__). As part of the 141 | issue, binary dependency was updated so that SPTK library can be 142 | compiled on linux, osx and Windows as well. 143 | - Remove unnecesarry array initialization 144 | (`#23 `__) 145 | 146 | v0.1.2 <2015-09-12> 147 | ------------------- 148 | 149 | - Add ``pysptk.synthesis`` package that provides high level interfaces 150 | for speech waveform synthesis 151 | (`#14 `__) 152 | - Add cross-link to the docs 153 | - Add ``pysptk.conversion.mgc2b`` 154 | - Add speech analysis and re-synthesis demonstration notebook 155 | (`#13 `__) 156 | - Add ``pysptk.util.example_audio_file`` 157 | - Add ``fftcep`` (`#18 `__) 158 | - Add ``mfcc`` (`#21 `__) 159 | - Cython is now only required to build development versioni of pysptk. 160 | (`#8 `__) 161 | 162 | v0.1.1 <2015-09-05> 163 | ------------------- 164 | 165 | - Include \*.c to pypi distribution 166 | 167 | v0.1.0 <2015-09-05> 168 | ------------------- 169 | 170 | - Initial release 171 | 172 | .. _#54: https://github.com/r9y9/pysptk/pull/54 173 | .. _#55: https://github.com/r9y9/pysptk/issues/55 174 | .. _#63: https://github.com/r9y9/pysptk/pull/63 175 | .. _#62: https://github.com/r9y9/pysptk/issues/62 176 | .. _#64: https://github.com/r9y9/pysptk/pull/64 177 | .. _#65: https://github.com/r9y9/pysptk/issues/65 178 | .. _#67: https://github.com/r9y9/pysptk/pull/67 179 | .. _#72: https://github.com/r9y9/pysptk/issues/72 180 | .. _#75: https://github.com/r9y9/pysptk/pull/75 181 | .. _#83: https://github.com/r9y9/pysptk/pull/83 182 | .. _#87: https://github.com/r9y9/pysptk/pull/87 183 | .. _#92: https://github.com/r9y9/pysptk/pull/92 184 | .. _#96: https://github.com/r9y9/pysptk/pull/96 185 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # pysptk documentation build configuration file, created by 4 | # sphinx-quickstart on Fri Sep 4 18:38:55 2015. 5 | # 6 | # This file is execfile()d with the current directory set to its 7 | # containing dir. 8 | # 9 | # Note that not all possible configuration values are present in this 10 | # autogenerated file. 11 | # 12 | # All configuration values have a default; values that are commented out 13 | # serve to show the default. 14 | 15 | import os 16 | 17 | import pkg_resources 18 | 19 | __version__ = pkg_resources.get_distribution("pysptk").version 20 | 21 | # If extensions (or modules to document with autodoc) are in another directory, 22 | # add these directories to sys.path here. If the directory is relative to the 23 | # documentation root, use os.path.abspath to make it absolute, like shown here. 24 | # sys.path.insert(0, os.path.abspath('.')) 25 | 26 | ON_RTD = os.environ.get("READTHEDOCS", None) == "True" 27 | 28 | # -- General configuration ------------------------------------------------ 29 | 30 | # If your documentation needs a minimal Sphinx version, state it here. 31 | # needs_sphinx = '1.0' 32 | 33 | # Add any Sphinx extension module names here, as strings. They can be 34 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 35 | # ones. 36 | extensions = [ 37 | "sphinx.ext.autodoc", 38 | "sphinx.ext.autosummary", 39 | "sphinx.ext.doctest", 40 | "sphinx.ext.mathjax", 41 | "sphinx.ext.viewcode", 42 | "numpydoc", 43 | "matplotlib.sphinxext.plot_directive", 44 | ] 45 | 46 | if ON_RTD: 47 | # Remove extensions not currently supported on RTD 48 | extensions.remove("matplotlib.sphinxext.plot_directive") 49 | 50 | autosummary_generate = True 51 | numpydoc_show_class_members = False 52 | 53 | # Most of plotting settings are copy and pasted from librosa 54 | # https://github.com/bmcfee/librosa 55 | 56 | if not ON_RTD: 57 | # Determine if the matplotlib has a recent enough version of the 58 | # plot_directive. 59 | try: 60 | from matplotlib.sphinxext import plot_directive 61 | except ImportError: 62 | use_matplotlib_plot_directive = False 63 | else: 64 | try: 65 | print("plot_directive.__version__:", plot_directive.__version__) 66 | use_matplotlib_plot_directive = plot_directive.__version__ >= 2 67 | except AttributeError: 68 | use_matplotlib_plot_directive = False 69 | 70 | if use_matplotlib_plot_directive: 71 | extensions.append("matplotlib.sphinxext.plot_directive") 72 | else: 73 | raise RuntimeError("You need a recent enough version of matplotlib") 74 | 75 | # ------------------------------------------------------------------------------ 76 | # Plot 77 | # ------------------------------------------------------------------------------ 78 | plot_pre_code = """ 79 | import seaborn 80 | seaborn.set(style='ticks') 81 | import numpy as np 82 | import pysptk 83 | np.random.seed(123) 84 | np.set_printoptions(precision=3, linewidth=64, edgeitems=2, threshold=200) 85 | """ 86 | plot_include_source = True 87 | plot_formats = [("png", 96), "pdf"] 88 | plot_html_show_formats = False 89 | 90 | font_size = 13 * 72 / 96.0 # 13 px 91 | 92 | plot_rcparams = { 93 | "font.size": font_size, 94 | "axes.titlesize": font_size, 95 | "axes.labelsize": font_size, 96 | "xtick.labelsize": font_size, 97 | "ytick.labelsize": font_size, 98 | "legend.fontsize": font_size, 99 | "figure.subplot.bottom": 0.2, 100 | "figure.subplot.left": 0.2, 101 | "figure.subplot.right": 0.9, 102 | "figure.subplot.top": 0.85, 103 | "figure.subplot.wspace": 0.4, 104 | "text.usetex": False, 105 | } 106 | 107 | if not ON_RTD: 108 | import matplotlib 109 | 110 | matplotlib.rcParams.update(plot_rcparams) 111 | 112 | 113 | # Generate plots for example sections 114 | numpydoc_use_plots = True 115 | 116 | # Add any paths that contain templates here, relative to this directory. 117 | templates_path = ["_templates"] 118 | 119 | # The suffix(es) of source filenames. 120 | # You can specify multiple suffix as a list of string: 121 | # source_suffix = ['.rst', '.md'] 122 | source_suffix = ".rst" 123 | 124 | # The encoding of source files. 125 | # source_encoding = 'utf-8-sig' 126 | 127 | # The master toctree document. 128 | master_doc = "index" 129 | 130 | # General information about the project. 131 | project = "pysptk" 132 | copyright = "2015, Ryuichi YAMAMOTO" 133 | author = "Ryuichi YAMAMOTO" 134 | 135 | # The version info for the project you're documenting, acts as replacement for 136 | # |version| and |release|, also used in various other places throughout the 137 | # built documents. 138 | # 139 | # The short X.Y version. 140 | version = __version__ 141 | # The full version, including alpha/beta/rc tags. 142 | release = __version__ 143 | 144 | # The language for content autogenerated by Sphinx. Refer to documentation 145 | # for a list of supported languages. 146 | # 147 | # This is also used if you do content translation via gettext catalogs. 148 | # Usually you set "language" from the command line for these cases. 149 | language = None 150 | 151 | # There are two options for replacing |today|: either, you set today to some 152 | # non-false value, then it is used: 153 | # today = '' 154 | # Else, today_fmt is used as the format for a strftime call. 155 | # today_fmt = '%B %d, %Y' 156 | 157 | # List of patterns, relative to source directory, that match files and 158 | # directories to ignore when looking for source files. 159 | exclude_patterns = ["_build"] 160 | 161 | # The reST default role (used for this markup: `text`) to use for all 162 | # documents. 163 | # default_role = None 164 | 165 | # If true, '()' will be appended to :func: etc. cross-reference text. 166 | # add_function_parentheses = True 167 | 168 | # If true, the current module name will be prepended to all description 169 | # unit titles (such as .. function::). 170 | # add_module_names = True 171 | 172 | # If true, sectionauthor and moduleauthor directives will be shown in the 173 | # output. They are ignored by default. 174 | # show_authors = False 175 | 176 | # The name of the Pygments (syntax highlighting) style to use. 177 | pygments_style = "sphinx" 178 | 179 | # A list of ignored prefixes for module index sorting. 180 | # modindex_common_prefix = [] 181 | 182 | # If true, keep warnings as "system message" paragraphs in the built documents. 183 | # keep_warnings = False 184 | 185 | # If true, `todo` and `todoList` produce output, else they produce nothing. 186 | todo_include_todos = False 187 | 188 | 189 | # -- Options for HTML output ---------------------------------------------- 190 | 191 | # The theme to use for HTML and HTML Help pages. See the documentation for 192 | # a list of builtin themes. 193 | html_theme = "sphinx_rtd_theme" 194 | 195 | # Theme options are theme-specific and customize the look and feel of a theme 196 | # further. For a list of options available for each theme, see the 197 | # documentation. 198 | html_theme_options = { 199 | "collapse_navigation": False, 200 | "display_version": True, 201 | "logo_only": True, 202 | } 203 | 204 | # Add any paths that contain custom themes here, relative to this directory. 205 | # html_theme_path = [] 206 | 207 | # The name for this set of Sphinx documents. If None, it defaults to 208 | # " v documentation". 209 | # html_title = None 210 | 211 | # A shorter title for the navigation bar. Default is the same as html_title. 212 | # html_short_title = None 213 | 214 | # The name of an image file (relative to this directory) to place at the top 215 | # of the sidebar. 216 | # html_logo = None 217 | 218 | # The name of an image file (within the static path) to use as favicon of the 219 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 220 | # pixels large. 221 | # html_favicon = None 222 | 223 | # Add any paths that contain custom static files (such as style sheets) here, 224 | # relative to this directory. They are copied after the builtin static files, 225 | # so a file named "default.css" will overwrite the builtin "default.css". 226 | html_static_path = ["_static"] 227 | 228 | # Add any extra paths that contain custom files (such as robots.txt or 229 | # .htaccess) here, relative to this directory. These files are copied 230 | # directly to the root of the documentation. 231 | # html_extra_path = [] 232 | 233 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 234 | # using the given strftime format. 235 | # html_last_updated_fmt = '%b %d, %Y' 236 | 237 | # If true, SmartyPants will be used to convert quotes and dashes to 238 | # typographically correct entities. 239 | # html_use_smartypants = True 240 | 241 | # Custom sidebar templates, maps document names to template names. 242 | # html_sidebars = {} 243 | 244 | # Additional templates that should be rendered to pages, maps page names to 245 | # template names. 246 | # html_additional_pages = {} 247 | 248 | # If false, no module index is generated. 249 | # html_domain_indices = True 250 | 251 | # If false, no index is generated. 252 | # html_use_index = True 253 | 254 | # If true, the index is split into individual pages for each letter. 255 | # html_split_index = False 256 | 257 | # If true, links to the reST sources are added to the pages. 258 | # html_show_sourcelink = True 259 | 260 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 261 | # html_show_sphinx = True 262 | 263 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 264 | # html_show_copyright = True 265 | 266 | # If true, an OpenSearch description file will be output, and all pages will 267 | # contain a tag referring to it. The value of this option must be the 268 | # base URL from which the finished HTML is served. 269 | # html_use_opensearch = '' 270 | 271 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 272 | # html_file_suffix = None 273 | 274 | # Language to be used for generating the HTML full-text search index. 275 | # Sphinx supports the following languages: 276 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' 277 | # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' 278 | # html_search_language = 'en' 279 | 280 | # A dictionary with options for the search language support, empty by default. 281 | # Now only 'ja' uses this config value 282 | # html_search_options = {'type': 'default'} 283 | 284 | # The name of a javascript file (relative to the configuration directory) that 285 | # implements a search results scorer. If empty, the default will be used. 286 | # html_search_scorer = 'scorer.js' 287 | 288 | # Output file base name for HTML help builder. 289 | htmlhelp_basename = "pysptkdoc" 290 | 291 | # -- Options for LaTeX output --------------------------------------------- 292 | 293 | latex_elements = {} 294 | 295 | # Grouping the document tree into LaTeX files. List of tuples 296 | # (source start file, target name, title, 297 | # author, documentclass [howto, manual, or own class]). 298 | latex_documents = [ 299 | (master_doc, "pysptk.tex", "pysptk Documentation", "Ryuichi YAMAMOTO", "manual"), 300 | ] 301 | 302 | # The name of an image file (relative to this directory) to place at the top of 303 | # the title page. 304 | # latex_logo = None 305 | 306 | # For "manual" documents, if this is true, then toplevel headings are parts, 307 | # not chapters. 308 | # latex_use_parts = False 309 | 310 | # If true, show page references after internal links. 311 | # latex_show_pagerefs = False 312 | 313 | # If true, show URL addresses after external links. 314 | # latex_show_urls = False 315 | 316 | # Documents to append as an appendix to all manuals. 317 | # latex_appendices = [] 318 | 319 | # If false, no module index is generated. 320 | # latex_domain_indices = True 321 | 322 | 323 | # -- Options for manual page output --------------------------------------- 324 | 325 | # One entry per manual page. List of tuples 326 | # (source start file, name, description, authors, manual section). 327 | man_pages = [(master_doc, "pysptk", "pysptk Documentation", [author], 1)] 328 | 329 | # If true, show URL addresses after external links. 330 | # man_show_urls = False 331 | 332 | 333 | # -- Options for Texinfo output ------------------------------------------- 334 | 335 | # Grouping the document tree into Texinfo files. List of tuples 336 | # (source start file, target name, title, author, 337 | # dir menu entry, description, category) 338 | texinfo_documents = [ 339 | ( 340 | master_doc, 341 | "pysptk", 342 | "pysptk Documentation", 343 | author, 344 | "pysptk", 345 | "One line description of project.", 346 | "Miscellaneous", 347 | ), 348 | ] 349 | 350 | # Documents to append as an appendix to all manuals. 351 | # texinfo_appendices = [] 352 | 353 | # If false, no module index is generated. 354 | # texinfo_domain_indices = True 355 | 356 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 357 | # texinfo_show_urls = 'footnote' 358 | 359 | # If true, do not generate a @detailmenu in the "Top" node's menu. 360 | # texinfo_no_detailmenu = False 361 | -------------------------------------------------------------------------------- /docs/conversion.rst: -------------------------------------------------------------------------------- 1 | .. automodule:: pysptk.conversion 2 | -------------------------------------------------------------------------------- /docs/development.rst: -------------------------------------------------------------------------------- 1 | Developer Documentation 2 | ======================= 3 | 4 | Design principle 5 | ---------------- 6 | 7 | pysptk is a thin python wrapper of SPTK. It is designed to be API consistent 8 | with the original SPTK as possible, but give better interface. There are a few 9 | design principles to wrap C interface: 10 | 11 | 1. Avoid really short names for variables (e.g. a, b, c, aa, bb, dd) 12 | 13 | Variable names should be informative. If the C functions have such short 14 | names, use self-descriptive names instead for python interfaces, unless 15 | they have clear meanings in their context. 16 | 17 | 2. Avoid too many function arguments 18 | 19 | Less is better. If the C functions have too many function arguments, use 20 | keyword arguments with proper default values for optional ones in python. 21 | 22 | 3. Handle errors in python 23 | 24 | Since C functions might `exit` (unfortunately) inside their functions for 25 | unexpected inputs, it should be check if the inputs are supported or not 26 | in python. 27 | 28 | To wrap C interface, Cython is totally used. 29 | 30 | 31 | How to build pysptk 32 | ------------------- 33 | 34 | You have to install ``numpy`` and ``cython`` first, and then: 35 | 36 | :: 37 | 38 | git clone https://github.com/r9y9/pysptk 39 | cd pysptk 40 | git submodule update --init 41 | python setup.py develop 42 | 43 | should work. 44 | 45 | .. note:: 46 | 47 | Dependency to the SPTK is added as a submodule. You have to checkout the 48 | supported SPTK as ``git sudmobule update --init`` before running setup.py. 49 | 50 | 51 | How to build docs 52 | ----------------- 53 | 54 | pysptk docs are managed by the python sphinx. Docs-related dependencies can be 55 | resolved by: 56 | 57 | .. code:: 58 | 59 | pip install .[docs] 60 | 61 | at the top of pysptk directory. 62 | 63 | To build docs, go to the `docs` directory and then: 64 | 65 | .. code:: 66 | 67 | make html 68 | 69 | You will see the generated docs in `_build` directory as follows (might 70 | different depends on sphinx version): 71 | 72 | :: 73 | 74 | % tree _build/ -d 75 | _build/ 76 | ├── doctrees 77 | │   └── generated 78 | ├── html 79 | │   ├── _images 80 | │   ├── _modules 81 | │   │   └── pysptk 82 | │   ├── _sources 83 | │   │   └── generated 84 | │   ├── _static 85 | │   │   ├── css 86 | │   │   ├── fonts 87 | │   │   └── js 88 | │   └── generated 89 | └── plot_directive 90 | └── generated 91 | 92 | 93 | See `_build/html/index.html` for the top page of the generated docs. 94 | 95 | 96 | How to add a new function 97 | ------------------------- 98 | 99 | There are a lot of functions unexposed from SPTK. To add a new function to pysptk, 100 | there are a few typical steps: 101 | 102 | 1. Add function signature to ``_sptk.pxd`` 103 | 2. Add cython implementation to ``_sptk.pyx`` 104 | 3. Add python interface (with docstrings) to ``sptk.py`` (or some proper module) 105 | 106 | As you can see in setup.py, ``_sptk.pyx`` and SPTK sources are compiled into a 107 | single extension module. 108 | 109 | .. note:: 110 | 111 | You might wonder why cython implementation and python interface should be 112 | separated because cython module can be directly accessed by python. The 113 | reasons are 1) to avoid rebuilding cython module when docs strings are 114 | changed in the source 2) to make doc looks great, since sphinx seems 115 | unable to collect function argments correctly from cython module for now. 116 | Relevant issue: `pysptk/#33`_ 117 | 118 | .. _pysptk/#33: https://github.com/r9y9/pysptk/issues/33 119 | 120 | 121 | An example 122 | ~~~~~~~~~~~~~~~ 123 | 124 | In _sptk.pyd: 125 | 126 | .. code:: 127 | 128 | cdef extern from "SPTK.h": 129 | double _agexp "agexp"(double r, double x, double y) 130 | 131 | In _sptk.pyx: 132 | 133 | .. code:: 134 | 135 | def agexp(r, x, y): 136 | return _agexp(r, x, y) 137 | 138 | In sptk.pyx: 139 | 140 | .. code:: 141 | 142 | def agexp(r, x, y): 143 | """Magnitude squared generalized exponential function 144 | 145 | Parameters 146 | ---------- 147 | r : float 148 | Gamma 149 | x : float 150 | Real part 151 | y : float 152 | Imaginary part 153 | 154 | Returns 155 | ------- 156 | Value 157 | 158 | """ 159 | return _sptk.agexp(r, x, y) 160 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. pysptk documentation master file, created by 2 | sphinx-quickstart on Fri Sep 4 18:38:55 2015. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | :github_url: https://github.com/r9y9/pysptk 7 | 8 | pysptk 9 | ====== 10 | 11 | .. automodule:: pysptk 12 | 13 | Installation guide 14 | ------------------ 15 | 16 | .. toctree:: 17 | :maxdepth: 2 18 | 19 | introduction 20 | 21 | 22 | API documentation 23 | ----------------- 24 | 25 | .. toctree:: 26 | :maxdepth: 2 27 | 28 | api 29 | 30 | 31 | Developer Documentation 32 | ----------------------- 33 | 34 | .. toctree:: 35 | :maxdepth: 2 36 | 37 | development 38 | 39 | 40 | .. toctree:: 41 | :maxdepth: 1 42 | :caption: Meta information 43 | 44 | changelog 45 | 46 | Indices and tables 47 | ================== 48 | 49 | * :ref:`genindex` 50 | * :ref:`search` 51 | -------------------------------------------------------------------------------- /docs/introduction.rst: -------------------------------------------------------------------------------- 1 | Installation guide 2 | ================== 3 | 4 | The latest release is availabe on pypi. Assuming you have already ``numpy`` installed, you can install pysptk by: 5 | 6 | .. code:: 7 | 8 | pip install pysptk 9 | 10 | If yout want the latest development version, run: 11 | 12 | .. code:: 13 | 14 | pip install git+https://github.com/r9y9/pysptk 15 | 16 | or: 17 | 18 | .. code:: 19 | 20 | git clone https://github.com/r9y9/pysptk 21 | cd pysptk 22 | python setup.py develop # or install 23 | 24 | This should resolve the package dependencies and install ``pysptk`` property. 25 | 26 | 27 | .. note:: 28 | 29 | If you use the development version, you need to have ``cython`` (and C compiler) installed to compile cython module(s). 30 | 31 | Workaround for ``ValueError: numpy.ndarray size changed, may indicate binary incompatibility`` 32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 33 | 34 | This type of errors comes from the Numpys' ABI breaking changes. If you see ``ValueError: numpy.ndarray size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject`` or similar, please make sure to install numpy first, and then install pyopenjtalk by: 35 | 36 | .. code:: 37 | 38 | pip install pysptk --no-build-isolation 39 | 40 | or: 41 | 42 | .. code:: 43 | 44 | pip install git+https://github.com/r9y9/pysptk --no-build-isolation 45 | 46 | The option ``--no-build-isolation`` tells pip not to create a build environment, so the pre-installed numpy is used to build the packge. Hense there should be no Numpy's ABI issues. 47 | 48 | For Windows users 49 | ^^^^^^^^^^^^^^^^^ 50 | 51 | There are some binary wheels available on pypi, so you can install ``pysptk`` via pip **without cython and C compilier** if there exists a binary wheel that matches your environment (depends on bits of system and python version). For now, wheels are available for: 52 | 53 | * Python 2.7 on 32 bit system 54 | * Python 2.7 on 64 bit system 55 | * Python 3.4 on 32 bit system 56 | 57 | If there is no binary wheel available for your environment, you can build ``pysptk`` from the source distribution, which is also available on pypi. Note that in order to compile ``pysptk`` from source in Windows, it is highly recommended to use `Anaconda 58 | `_ , since installation of numpy, cython and other scientific packages is really easy. In fact, continuous integration in Windows on AppVeyor uses Anacona to build and test ``pysptk``. See `pysptk/appveyor.yml `_ for the exact build steps. 59 | -------------------------------------------------------------------------------- /docs/sptk.rst: -------------------------------------------------------------------------------- 1 | Core SPTK API 2 | ============= 3 | 4 | All functionality in ``pysptk.sptk`` (the core API) is directly accesible from the top-level ``pysptk.*`` namespace. 5 | 6 | 7 | For convenience, vector-to-vector functions (``pysptk.mcep``, ``pysptk.mc2b``, etc) that takes an input vector as the first argment, can also accept matrix. As for matrix inputs, vector-to-vector functions are applied along with the last axis internally; e.g. 8 | 9 | .. code:: 10 | 11 | mc = pysptk.mcep(frames) # frames.shape == (num_frames, frame_len) 12 | 13 | is equivalent to: 14 | 15 | .. code:: 16 | 17 | mc = np.apply_along_axis(pysptk.mcep, -1, frames) 18 | 19 | 20 | .. warning:: The core APIs in ``pysptk.sptk`` package are based on the SPTK's internal APIs (e.g. code in ``_mgc2sp.c``), so the functionalities are not exactly same as SPTK's CLI. If you find any inconsistency that should be addressed, please file an issue. 21 | 22 | .. note:: Almost all of pysptk functions assume that the input array is **C-contiguous** and has ``float64`` element type. For vector-to-vector functions, the input array is automatically converted to ``float64``-typed one, the function is executed on it, and then the output array is converted to have the same type with the input you provided. 23 | 24 | .. note:: 25 | 26 | .. automodule:: pysptk.sptk 27 | -------------------------------------------------------------------------------- /docs/synthesis.rst: -------------------------------------------------------------------------------- 1 | .. automodule:: pysptk.synthesis 2 | -------------------------------------------------------------------------------- /docs/util.rst: -------------------------------------------------------------------------------- 1 | .. automodule:: pysptk.util 2 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "wheel", 4 | "setuptools", 5 | "cython>=0.28.0", 6 | "numpy>=v1.20.0", 7 | "scipy", 8 | ] 9 | 10 | 11 | [tool.pysen] 12 | version = "0.10.2" 13 | 14 | [tool.pysen.lint] 15 | enable_black = true 16 | enable_flake8 = true 17 | enable_isort = true 18 | enable_mypy = false 19 | mypy_preset = "entry" 20 | line_length = 88 21 | py_version = "py38" 22 | 23 | [[tool.pysen.lint.mypy_targets]] 24 | paths = ["pysptk", "tests"] 25 | -------------------------------------------------------------------------------- /pysptk/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | A python wrapper for `Speech Signal Processing Toolkit (SPTK) 3 | `_. 4 | 5 | https://github.com/r9y9/pysptk 6 | 7 | The wrapper is based on a modified version of SPTK (`r9y9/SPTK`_) 8 | 9 | .. _r9y9/SPTK: https://github.com/r9y9/SPTK 10 | 11 | Full documentation 12 | ------------------ 13 | 14 | A full documentation of SPTK is available at http://sp-tk.sourceforge.net. 15 | If you are not familiar with SPTK, I recommend you to take a look at the doc 16 | first before using ``pysptk``. 17 | 18 | Demonstration notebooks 19 | ----------------------- 20 | 21 | * `Introduction notebook`_: a brief introduction to pysptk 22 | * `Speech analysis and re-synthesis resynthesis notebook`_: a demonstration \ 23 | notebook for speech analysis and re-synthesis. Synthesized audio examples\ 24 | (English) are available on the notebook. 25 | 26 | .. _Introduction notebook: \ 27 | http://nbviewer.ipython.org/github/r9y9/pysptk/blob/master/examples/\ 28 | pysptk%20introduction.ipynb 29 | .. _Speech analysis and re-synthesis resynthesis notebook:\ 30 | http://nbviewer.ipython.org/github/r9y9/pysptk/blob/master/examples/\ 31 | Speech%20analysis%20and%20re-synthesis.ipynb 32 | 33 | """ 34 | 35 | from . import synthesis, util # noqa 36 | from .conversion import mc2e, mc2sp, mgc2b, sp2mc # noqa 37 | from .sptk import * # noqa 38 | from .version import __version__ # noqa 39 | -------------------------------------------------------------------------------- /pysptk/_sptk.pxd: -------------------------------------------------------------------------------- 1 | ### Definitions ### 2 | 3 | cdef enum Window: 4 | BLACKMAN = 0 5 | HAMMING = 1 6 | HANNING = 2 7 | BARTLETT = 3 8 | TRAPEZOID = 4 9 | RECTANGULAR = 5 10 | 11 | cdef enum Boolean: 12 | FA = 0 13 | TR = 1 14 | 15 | cdef extern from "SPTK.h": 16 | 17 | # Library routines 18 | double _agexp "agexp"(double r, double x, double y) 19 | double _gexp "gexp"(const double r, const double x) 20 | double _glog "glog"(const double r, const double x) 21 | int _mseq "mseq"() 22 | 23 | 24 | void _acorr "acorr"(double *x, int l, double *r, const int np) 25 | 26 | # Adaptive mel-generalized cepstrum analysis 27 | double _acep "acep"(double x, double *c, const int m, const double lambda_coef, 28 | const double step, const double tau, const int pd, 29 | const double eps); 30 | double _agcep "agcep"(double x, double *c, const int m, const int stage, 31 | const double lambda_coef, const double step, const double tau, 32 | const double eps); 33 | double _amcep "amcep"(double x, double *b, const int m, const double a, 34 | const double lambda_coef, const double step, const double tau, 35 | const int pd, const double eps); 36 | 37 | # Mel-generalized cepstrum analysis 38 | int _mcep "mcep"(double *xw, const int flng, double *mc, const int m, const double a, 39 | const int itr1, const int itr2, const double dd, const int etype, 40 | const double e, const double f, const int itype) 41 | int _gcep "gcep"(double *xw, const int flng, double *gc, const int m, const double g, 42 | const int itr1, const int itr2, const double d, const int etype, 43 | const double e, const double f, const int itype) 44 | int _mgcep "mgcep"(double *xw, int flng, double *b, const int m, const double a, 45 | const double g, const int n, const int itr1, const int itr2, 46 | const double dd, const int etype, const double e, const double f, 47 | const int itype) 48 | int _uels "uels"(double *xw, const int flng, double *c, const int m, const int itr1, 49 | const int itr2, const double dd, const int etype, const double e, 50 | const int itype) 51 | void _fftcep "fftcep"(double *sp, const int flng, double *c, const int m, int itr, 52 | double ac) 53 | int _lpc "lpc"(double *x, const int flng, double *a, const int m, const double f) 54 | 55 | 56 | # MFCC 57 | void _mfcc "mfcc"(double *in_mfcc, double *mc, const double sampleFreq, 58 | const double alpha, const double eps, const int wlng, 59 | const int flng, const int m, const int n, const int ceplift, 60 | const Boolean dftmode, const Boolean usehamming) 61 | 62 | # LPC, LSP and PARCOR conversions 63 | void _lpc2c "lpc2c"(double *a, int m1, double *c, const int m2) 64 | int _lpc2lsp "lpc2lsp"(double *lpc, double *lsp, const int order, const int numsp, 65 | const int maxitr, const double eps) 66 | int _lpc2par "lpc2par"(double *a, double *k, const int m) 67 | void _par2lpc "par2lpc"(double *k, double *a, const int m) 68 | void _lsp2lpc "lsp2lpc"(double *lsp, double *a, const int m) 69 | void _lsp2sp "lsp2sp"(double *lsp, const int m, double *x, const int l, const int gain) 70 | 71 | 72 | # Mel-generalized cepstrum conversions 73 | void _mc2b "mc2b"(double *mc, double *b, int m, const double a) 74 | void _b2mc "b2mc"(double *b, double *mc, int m, const double a) 75 | void _b2c "b2c"(double *b, int m1, double *c, int m2, double a) 76 | void _c2acr "c2acr"(double *c, const int m1, double *r, const int m2, const int flng) 77 | void _c2ir "c2ir"(double *c, const int nc, double *h, const int leng) 78 | void _ic2ir "ic2ir"(double *h, const int leng, double *c, const int nc) 79 | void _c2ndps "c2ndps"(double *c, const int m, double *n, const int l) 80 | void _ndps2c "ndps2c"(double *n, const int l, double *c, const int m) 81 | void _gc2gc "gc2gc"(double *c1, const int m1, const double g1, double *c2, const int m2, 82 | const double g2) 83 | void _gnorm "gnorm"(double *c1, double *c2, int m, const double g) 84 | void _ignorm "ignorm"(double *c1, double *c2, int m, const double g) 85 | void _freqt "freqt"(double *c1, const int m1, double *c2, const int m2, const double a) 86 | void _frqtr "frqtr"(double *c1, int m1, double *c2, int m2, const double a) 87 | void _mgc2mgc "mgc2mgc"(double *c1, const int m1, const double a1, const double g1, 88 | double *c2, const int m2, const double a2, const double g2) 89 | void _mgc2sp "mgc2sp"(double *mgc, const int m, const double a, const double g, double *x, 90 | double *y, const int flng) 91 | void _mgclsp2sp "mgclsp2sp"(double a, double g, double *lsp, const int m, double *x, 92 | const int l, const int gain) 93 | 94 | 95 | # F0 analysis 96 | void _swipe "swipe"(double *input, double *output, int length, int samplerate, 97 | int frame_shift, double min, double max, double st, int otype) 98 | int _rapt "rapt"(float * input, float * output, int length, double sample_freq, 99 | int frame_shift, double minF0, double maxF0, double voice_bias, 100 | int otype) 101 | 102 | 103 | # Excitation 104 | void _excite "excite"(double *pitch, int n, double *out, int fprd, int iprd, Boolean gauss, int seed_i) 105 | 106 | # Waveform generation filters 107 | double _zerodf "zerodf"(double x, double *b, int m, double *d) 108 | double _zerodft "zerodft"(double x, double *b, const int m, double *d) 109 | double _poledf "poledf"(double x, double *a, int m, double *d) 110 | double _poledft "poledft"(double x, double *a, int m, double *d) 111 | double _lmadf "lmadf"(double x, double *c, const int m, const int pd, double *d) 112 | double _lmadft "lmadft"(double x, double *c, const int m, const int pd, double *d, 113 | int block_num, int *block_size) 114 | double _lspdf_even "lspdf_even"(double x, double *f, const int m, double *d) 115 | double _lspdf_odd "lspdf_odd"(double x, double *f, const int m, double *d) 116 | double _ltcdf "ltcdf"(double x, double *k, int m, double *d) 117 | double _glsadf "glsadf"(double x, double *c, const int m, const int n, double *d) 118 | double _glsadft "glsadft"(double x, double *c, const int m, const int n, double *d) 119 | double _iglsadf "iglsadf"(double x, double *c, const int m, const int n, double *d) 120 | double _iglsadft "iglsadft"(double x, double *c, const int m, const int n, double *d) 121 | double _mlsadf "mlsadf"(double x, double *b, const int m, const double a, const int pd, 122 | double *d) 123 | double _mlsadft "mlsadft"(double x, double *b, const int m, const double a, const int pd, 124 | double *d) 125 | double _mglsadf "mglsadf"(double x, double *b, const int m, const double a, const int n, 126 | double *d) 127 | double _mglsadft "mglsadft"(double x, double *b, const int m, const double a, const int n, 128 | double *d) 129 | double _imglsadf "imglsadf"(double x, double *b, const int m, const double a, const int n, 130 | double *d) 131 | double _imglsadft "imglsadft"(double x, double *b, const int m, const double a, const int n, 132 | double *d) 133 | 134 | # Window functions 135 | double _window "window"(Window window_type, double *x, const int size, const int nflg) 136 | 137 | # Utils 138 | int _lspcheck "lspcheck"(double *lsp, const int ord) 139 | void _phidf "phidf"(const double x, const int m, double a, double *d) 140 | int _levdur "levdur"(double *r, double *a, const int m, double eps) 141 | -------------------------------------------------------------------------------- /pysptk/_sptk.pyx: -------------------------------------------------------------------------------- 1 | # cython: boundscheck=True, wraparound=True 2 | 3 | import numpy as np 4 | cimport numpy as np 5 | np.import_array() 6 | 7 | cimport cython 8 | from . cimport _sptk 9 | 10 | from warnings import warn 11 | from pysptk.util import assert_gamma, assert_fftlen, assert_pade, assert_stage 12 | 13 | 14 | ### Library routines ### 15 | 16 | def agexp(r, x, y): 17 | return _agexp(r, x, y) 18 | 19 | 20 | def gexp(r, x): 21 | return _gexp(r, x) 22 | 23 | 24 | def glog(r, x): 25 | return _glog(r, x) 26 | 27 | 28 | def mseq(): 29 | return _mseq() 30 | 31 | 32 | def acorr(np.ndarray[np.float64_t, ndim=1, mode="c"] x not None, order): 33 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] r 34 | r = np.zeros(order + 1) 35 | _acorr(&x[0], len(x), &r[0], order) 36 | return r 37 | 38 | 39 | ### Adaptive mel-generalized cepstrum analysis ### 40 | 41 | def acep(x, np.ndarray[np.float64_t, ndim=1, mode="c"] c not None, 42 | lambda_coef=0.98, step=0.1, tau=0.9, pd=4, eps=1.0e-6): 43 | assert_pade(pd) 44 | cdef int order = len(c) - 1 45 | cdef double prederr 46 | prederr = _acep(x, &c[0], order, lambda_coef, step, tau, pd, eps) 47 | return prederr 48 | 49 | 50 | def agcep(x, np.ndarray[np.float64_t, ndim=1, mode="c"] c not None, 51 | stage=1, 52 | lambda_coef=0.98, step=0.1, tau=0.9, eps=1.0e-6): 53 | assert_stage(stage) 54 | 55 | cdef int order = len(c) - 1 56 | cdef double prederr 57 | prederr = _agcep(x, &c[0], order, stage, lambda_coef, step, tau, eps) 58 | return prederr 59 | 60 | 61 | def amcep(x, np.ndarray[np.float64_t, ndim=1, mode="c"] b not None, 62 | alpha=0.35, 63 | lambda_coef=0.98, step=0.1, tau=0.9, pd=4, eps=1.0e-6): 64 | assert_pade(pd) 65 | cdef int order = len(b) - 1 66 | cdef double prederr 67 | prederr = _amcep(x, &b[0], order, alpha, lambda_coef, step, tau, pd, eps) 68 | return prederr 69 | 70 | 71 | ### Mel-generalized cepstrum analysis ### 72 | 73 | def mcep(np.ndarray[np.float64_t, ndim=1, mode="c"] windowed not None, 74 | order=25, alpha=0.35, 75 | miniter=2, 76 | maxiter=30, 77 | threshold=0.001, 78 | etype=0, 79 | eps=0.0, 80 | min_det=1.0e-6, 81 | itype=0): 82 | if not itype in range(0, 5): 83 | raise ValueError("unsupported itype: %d, must be in 0:4" % itype) 84 | 85 | if not etype in range(0, 3): 86 | raise ValueError("unsupported etype: %d, must be in 0:2" % etype) 87 | 88 | if etype == 0 and eps != 0.0: 89 | raise ValueError("eps cannot be specified for etype = 0") 90 | 91 | if etype == 1 and eps < 0.0: 92 | raise ValueError("eps: %f, must be >= 0" % eps) 93 | 94 | if etype == 2 and eps >= 0.0: 95 | raise ValueError("eps: %f, must be < 0" % eps) 96 | 97 | if min_det < 0.0: 98 | raise ValueError("min_det must be positive: min_det = %f" % min_det) 99 | 100 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] x 101 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] mc 102 | cdef int frame_length 103 | if itype == 0: 104 | frame_length = len(windowed) 105 | else: 106 | frame_length = (len(windowed) - 1) * 2 # fftlen 107 | 108 | cdef int ret 109 | mc = np.empty(order + 1, dtype=np.float64) 110 | x = np.zeros(frame_length, dtype=np.float64) 111 | x[:len(windowed)] = windowed 112 | ret = _mcep(&x[0], frame_length, &mc[0], 113 | order, alpha, miniter, maxiter, threshold, etype, eps, 114 | min_det, itype) 115 | assert ret == -1 or ret == 0 or ret == 3 or ret == 4 116 | if ret == 3: 117 | raise RuntimeError("failed to compute mcep; error occured in theq") 118 | elif ret == 4: 119 | raise RuntimeError( 120 | "zero(s) are found in periodogram, use eps option to floor") 121 | 122 | return mc 123 | 124 | 125 | def gcep(np.ndarray[np.float64_t, ndim=1, mode="c"] windowed not None, 126 | order=25, gamma=0.0, 127 | miniter=2, 128 | maxiter=30, 129 | threshold=0.001, 130 | etype=0, 131 | eps=0.0, 132 | min_det=1.0e-6, 133 | itype=0, 134 | norm=False): 135 | assert_gamma(gamma) 136 | if not itype in range(0, 5): 137 | raise ValueError("unsupported itype: %d, must be in 0:4" % itype) 138 | 139 | if not etype in range(0, 3): 140 | raise ValueError("unsupported etype: %d, must be in 0:2" % etype) 141 | 142 | if etype == 0 and eps != 0.0: 143 | raise ValueError("eps cannot be specified for etype = 0") 144 | 145 | if (etype == 1 or etype == 2) and eps < 0.0: 146 | raise ValueError("eps: %f, must be >= 0" % eps) 147 | 148 | if min_det < 0.0: 149 | raise ValueError("min_det must be positive: min_det = %f" % min_det) 150 | 151 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] gc 152 | cdef int windowed_length = len(windowed) 153 | cdef int ret 154 | gc = np.empty(order + 1, dtype=np.float64) 155 | ret = _gcep(&windowed[0], windowed_length, &gc[0], order, 156 | gamma, miniter, maxiter, threshold, etype, eps, min_det, itype) 157 | assert ret == -1 or ret == 0 or ret == 3 158 | if ret == 3: 159 | raise RuntimeError("failed to compute gcep; error occured in theq") 160 | 161 | if not norm: 162 | _ignorm(&gc[0], &gc[0], order, gamma) 163 | 164 | return gc 165 | 166 | 167 | @cython.boundscheck(False) 168 | @cython.wraparound(False) 169 | def mgcep(np.ndarray[np.float64_t, ndim=1, mode="c"] windowed not None, 170 | order=25, alpha=0.35, gamma=0.0, 171 | num_recursions=None, 172 | miniter=2, 173 | maxiter=30, 174 | threshold=0.001, 175 | etype=0, 176 | eps=0.0, 177 | min_det=1.0e-6, 178 | itype=0, 179 | otype=0): 180 | assert_gamma(gamma) 181 | if not itype in range(0, 5): 182 | raise ValueError("unsupported itype: %d, must be in 0:4" % itype) 183 | 184 | if not etype in range(0, 3): 185 | raise ValueError("unsupported etype: %d, must be in 0:2" % etype) 186 | 187 | if etype == 0 and eps != 0.0: 188 | raise ValueError("eps cannot be specified for etype = 0") 189 | 190 | if (etype == 1 or etype == 2) and eps < 0.0: 191 | raise ValueError("eps: %f, must be >= 0" % eps) 192 | 193 | if min_det < 0.0: 194 | raise ValueError("min_det must be positive: min_det = %f" % min_det) 195 | 196 | if not otype in range(0, 6): 197 | raise ValueError("unsupported otype: %d, must be in 0:5" % otype) 198 | 199 | if num_recursions is None: 200 | num_recursions = len(windowed) - 1 201 | 202 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] mgc 203 | cdef int windowed_length = len(windowed) 204 | cdef int ret 205 | mgc = np.empty(order + 1, dtype=np.float64) 206 | ret = _mgcep(&windowed[0], windowed_length, &mgc[0], 207 | order, alpha, gamma, num_recursions, miniter, maxiter, 208 | threshold, etype, eps, min_det, itype) 209 | assert ret == -1 or ret == 0 or ret == 3 210 | if ret == 3: 211 | raise RuntimeError("failed to compute mgcep; error occured in theq") 212 | 213 | if otype == 0 or otype == 1 or otype == 2 or otype == 4: 214 | _ignorm(&mgc[0], &mgc[0], order, gamma) 215 | 216 | if otype == 0 or otype == 2 or otype == 4: 217 | _b2mc(&mgc[0], &mgc[0], order, alpha) 218 | 219 | if otype == 2 or otype == 4: 220 | _gnorm(&mgc[0], &mgc[0], order, gamma) 221 | 222 | cdef int i = 0 223 | cdef double g = gamma 224 | if otype == 4 or otype == 5: 225 | for i in range(1, len(mgc)): 226 | mgc[i] *= g 227 | 228 | return mgc 229 | 230 | 231 | def uels(np.ndarray[np.float64_t, ndim=1, mode="c"] windowed not None, 232 | order=25, 233 | miniter=2, 234 | maxiter=30, 235 | threshold=0.001, 236 | etype=0, 237 | eps=0.0, 238 | itype=0): 239 | if not itype in range(0, 5): 240 | raise ValueError("unsupported itype: %d, must be in 0:4" % itype) 241 | 242 | if not etype in range(0, 3): 243 | raise ValueError("unsupported etype: %d, must be in 0:2" % etype) 244 | 245 | if etype == 0 and eps != 0.0: 246 | raise ValueError("eps cannot be specified for etype = 0") 247 | 248 | if (etype == 1 or etype == 2) and eps < 0.0: 249 | raise ValueError("eps: %f, must be >= 0" % eps) 250 | 251 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] c 252 | cdef int windowed_length = len(windowed) 253 | cdef int ret 254 | c = np.empty(order + 1, dtype=np.float64) 255 | ret = _uels(&windowed[0], windowed_length, &c[0], order, 256 | miniter, maxiter, threshold, etype, eps, itype) 257 | assert ret == -1 or ret == 0 or ret == 3 258 | if ret == 3: 259 | raise RuntimeError( 260 | "zero(s) are found in periodogram, use eps option to floor") 261 | 262 | return c 263 | 264 | 265 | def fftcep(np.ndarray[np.float64_t, ndim=1, mode="c"] logsp not None, 266 | order=25, 267 | num_iter=0, 268 | acceleration_factor=0.0): 269 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] c 270 | cdef int logsp_length = len(logsp) 271 | c = np.empty(order + 1, dtype=np.float64) 272 | _fftcep(&logsp[0], logsp_length, &c[0], order, 273 | num_iter, acceleration_factor) 274 | 275 | return c 276 | 277 | 278 | def lpc(np.ndarray[np.float64_t, ndim=1, mode="c"] windowed not None, 279 | order=25, 280 | min_det=1.0e-6): 281 | if min_det < 0.0: 282 | raise ValueError("min_det must be positive: min_det = %f" % min_det) 283 | 284 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] a 285 | cdef int windowed_length = len(windowed) 286 | cdef int ret 287 | a = np.empty(order + 1, dtype=np.float64) 288 | ret = _lpc(&windowed[0], windowed_length, &a[0], order, min_det) 289 | assert ret == -2 or ret == -1 or ret == 0 290 | if ret == -2: 291 | warn("failed to compute `stable` LPC. Please try again with different paramters") 292 | elif ret == -1: 293 | raise RuntimeError( 294 | "failed to compute LPC. Please try again with different parameters") 295 | 296 | return a 297 | 298 | 299 | ### MFCC ### 300 | 301 | def mfcc(np.ndarray[np.float64_t, ndim=1, mode="c"] x not None, 302 | order=14, fs=16000, alpha=0.97, eps=1.0, window_len=None, 303 | frame_len=None, num_filterbanks=20, cepslift=22, use_dft=False, 304 | use_hamming=False, czero=False, power=False): 305 | if not (num_filterbanks > order): 306 | raise ValueError( 307 | "Number of filterbanks must be greater than order of MFCC") 308 | 309 | if window_len is None: 310 | window_len = len(x) 311 | if frame_len is None: 312 | frame_len = len(x) 313 | 314 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] cc 315 | cc = np.zeros(order + 2) 316 | 317 | cdef Boolean _dft_mode = TR if use_dft else FA 318 | cdef Boolean _use_hamming = TR if use_hamming else FA 319 | 320 | # after ccall we get 321 | # mfcc[0], mfcc[1], mfcc[2], ... mfcc[m-1], c0, Power 322 | _mfcc(&x[0], &cc[0], fs, alpha, eps, window_len, frame_len, order+1, 323 | num_filterbanks, cepslift, _dft_mode, _use_hamming) 324 | 325 | if (not czero) and power: 326 | cc[-2] = cc[-1] 327 | if not power: 328 | cc = cc[:-1] 329 | if not czero: 330 | cc = cc[:-1] 331 | 332 | return cc 333 | 334 | 335 | ### LPC, LSP and PARCOR conversions ### 336 | 337 | def lpc2c(np.ndarray[np.float64_t, ndim=1, mode="c"] lpc not None, 338 | order=None): 339 | if order is None: 340 | order = len(lpc) - 1 341 | 342 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] ceps 343 | cdef int src_order = len(lpc) - 1 344 | ceps = np.empty(order + 1, dtype=np.float64) 345 | _lpc2c(&lpc[0], src_order, &ceps[0], order) 346 | return ceps 347 | 348 | 349 | def lpc2lsp(np.ndarray[np.float64_t, ndim=1, mode="c"] lpc not None, 350 | numsp=128, maxiter=4, eps=1.0e-6, has_gain=True, 351 | loggain=False, otype=0, fs=None): 352 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] lsp 353 | cdef int lpc_start_idx = 1 if has_gain else 0 354 | cdef int order = len(lpc) - 1 if has_gain else len(lpc) 355 | cdef int ret 356 | lsp = np.zeros_like(lpc) 357 | ret = _lpc2lsp(&lpc[0], &lsp[lpc_start_idx], order, numsp, maxiter, eps) 358 | if otype == 0: 359 | lsp[lpc_start_idx:] *= 2 * np.pi 360 | elif otype == 2 or otype == 3: 361 | if fs is None: 362 | raise ValueError("fs must be specified when otype == 2 or 3") 363 | lsp[lpc_start_idx:] *= fs 364 | if ret == -1: 365 | raise RuntimeError("Failed to transform linear predictive coefficients to line spectral pairs") 366 | 367 | if otype == 3: 368 | lsp[lpc_start_idx:] *= 1000.0 369 | 370 | if has_gain: 371 | lsp[0] = lpc[0] 372 | if loggain: 373 | lsp[0] = np.log(lpc[0]) 374 | 375 | return lsp 376 | 377 | 378 | def lpc2par(np.ndarray[np.float64_t, ndim=1, mode="c"] lpc not None): 379 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] par 380 | par = np.empty_like(lpc) 381 | cdef int order = len(lpc) - 1 382 | _lpc2par(&lpc[0], &par[0], order) 383 | return par 384 | 385 | 386 | def par2lpc(np.ndarray[np.float64_t, ndim=1, mode="c"] par not None): 387 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] lpc 388 | lpc = np.empty_like(par) 389 | cdef int order = len(par) - 1 390 | _par2lpc(&par[0], &lpc[0], order) 391 | return lpc 392 | 393 | 394 | def lsp2lpc(np.ndarray[np.float64_t, ndim=1, mode="c"] lsp not None, 395 | has_gain=True, loggain=False, fs=None, itype=0): 396 | lsp = lsp.copy() 397 | cdef int lpc_start_idx = 1 if has_gain else 0 398 | 399 | if loggain and not has_gain: 400 | raise ValueError("has_gain must be True if you set loggain=True") 401 | 402 | if itype == 0: 403 | lsp[lpc_start_idx:] /= 2 * np.pi 404 | elif itype == 2 or itype == 3: 405 | if fs is None: 406 | raise ValueError("fs must be specified when itype == 2 or 3") 407 | lsp[lpc_start_idx:] /= fs 408 | 409 | if itype == 3: 410 | lsp[lpc_start_idx:] /= 1000.0 411 | 412 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] lpc 413 | cdef int order 414 | if has_gain: 415 | order = len(lsp) - 1 416 | else: 417 | order = len(lsp) 418 | lpc = np.empty_like(lsp) 419 | 420 | _lsp2lpc(&lsp[lpc_start_idx], &lpc[0], order) 421 | 422 | if has_gain: 423 | lpc[0] = lsp[0] 424 | if loggain: 425 | lpc[0] = np.exp(lpc[0]) 426 | 427 | return lpc 428 | 429 | 430 | def lsp2sp(np.ndarray[np.float64_t, ndim=1, mode="c"] lsp not None, 431 | fftlen=256, has_gain=True, loggain=False, fs=None, itype=0): 432 | assert_fftlen(fftlen) 433 | lsp = lsp.copy() 434 | cdef int lsp_start_idx = 1 if has_gain else 0 435 | 436 | if itype == 1: 437 | lsp[lsp_start_idx:] *= 2 * np.pi 438 | elif itype == 2 or itype == 3: 439 | if fs is None: 440 | raise ValueError("fs must be specified when itype == 2 or 3") 441 | lsp[lsp_start_idx:] = lsp[lsp_start_idx:] / fs * 2 * np.pi 442 | 443 | if itype == 3: 444 | lsp[lsp_start_idx:] /= 1000.0 445 | 446 | if loggain: 447 | lsp[0] = np.log(lsp[0]) 448 | 449 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] sp 450 | cdef int sp_length = (fftlen >> 1) + 1 451 | sp = np.empty(sp_length, dtype=np.float64) 452 | cdef int order = len(lsp) - 1 453 | _lsp2sp(&lsp[0], order, &sp[0], sp_length, 1 if has_gain else 0) 454 | return sp 455 | 456 | 457 | ### Mel-generalized cepstrum conversions ### 458 | 459 | def mc2b(np.ndarray[np.float64_t, ndim=1, mode="c"] mc not None, 460 | alpha=0.35): 461 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] b 462 | b = np.empty_like(mc) 463 | cdef int order = len(mc) - 1 464 | _mc2b(&mc[0], &b[0], order, alpha) 465 | return b 466 | 467 | 468 | def b2mc(np.ndarray[np.float64_t, ndim=1, mode="c"] b not None, 469 | alpha=0.35): 470 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] mc 471 | mc = np.empty_like(b) 472 | cdef int order = len(b) - 1 473 | _b2mc(&b[0], &mc[0], order, alpha) 474 | return mc 475 | 476 | 477 | def b2c(np.ndarray[np.float64_t, ndim=1, mode="c"] b not None, 478 | dst_order=None, 479 | alpha=0.35): 480 | cdef int src_order = len(b) - 1 481 | if dst_order is None: 482 | dst_order = src_order 483 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] c 484 | c = np.empty(dst_order + 1, dtype=np.float64) 485 | _b2c(&b[0], src_order, &c[0], dst_order, alpha) 486 | return c 487 | 488 | 489 | def c2acr(np.ndarray[np.float64_t, ndim=1, mode="c"] c not None, 490 | order=None, 491 | fftlen=256): 492 | assert_fftlen(fftlen) 493 | if len(c) > fftlen: 494 | raise ValueError("fftlen must be larger than length of input") 495 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] r 496 | cdef int src_order = len(c) - 1 497 | if order is None: 498 | order = src_order 499 | r = np.empty(order + 1, dtype=np.float64) 500 | _c2acr(&c[0], src_order, &r[0], order, fftlen) 501 | return r 502 | 503 | 504 | def c2ir(np.ndarray[np.float64_t, ndim=1, mode="c"] c not None, 505 | length=256): 506 | cdef int order = len(c) # NOT len(c) - 1 507 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] h 508 | h = np.empty(length, dtype=np.float64) 509 | _c2ir(&c[0], order, &h[0], length) 510 | return h 511 | 512 | 513 | def ic2ir(np.ndarray[np.float64_t, ndim=1, mode="c"] h not None, 514 | order=25): 515 | cdef int length = len(h) 516 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] c 517 | c = np.empty(order + 1, dtype=np.float64) 518 | _ic2ir(&h[0], length, &c[0], len(c)) 519 | return c 520 | 521 | 522 | @cython.boundscheck(False) 523 | @cython.wraparound(False) 524 | def c2ndps(np.ndarray[np.float64_t, ndim=1, mode="c"] c not None, 525 | fftlen=256): 526 | assert_fftlen(fftlen) 527 | cdef int dst_length = (fftlen >> 1) + 1 528 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] ndps, buf 529 | ndps = np.empty(dst_length, dtype=np.float64) 530 | cdef int order = len(c) - 1 531 | buf = np.empty(fftlen, dtype=np.float64) 532 | _c2ndps(&c[0], order, &buf[0], fftlen) 533 | 534 | ndps[:] = buf[0:dst_length] 535 | 536 | return ndps 537 | 538 | 539 | def ndps2c(np.ndarray[np.float64_t, ndim=1, mode="c"] ndps not None, 540 | order=25): 541 | # assuming the lenght of ndps is fftlen/2+1 542 | cdef int fftlen = (len(ndps) - 1) << 1 543 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] c 544 | assert_fftlen(fftlen) 545 | c = np.empty(order + 1, dtype=np.float64) 546 | _ndps2c(&ndps[0], fftlen, &c[0], order) 547 | return c 548 | 549 | 550 | def gc2gc(np.ndarray[np.float64_t, ndim=1, mode="c"] src_ceps not None, 551 | src_gamma=0.0, dst_order=None, dst_gamma=0.0): 552 | assert_gamma(src_gamma) 553 | assert_gamma(dst_gamma) 554 | 555 | cdef int src_order = len(src_ceps) - 1 556 | if dst_order is None: 557 | dst_order = src_order 558 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] dst_ceps 559 | dst_ceps = np.empty(dst_order + 1, dtype=np.float64) 560 | 561 | _gc2gc(&src_ceps[0], src_order, src_gamma, 562 | &dst_ceps[0], dst_order, dst_gamma) 563 | 564 | return dst_ceps 565 | 566 | 567 | def gnorm(np.ndarray[np.float64_t, ndim=1, mode="c"] ceps not None, 568 | gamma=0.0): 569 | assert_gamma(gamma) 570 | cdef int order = len(ceps) - 1 571 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] dst_ceps 572 | dst_ceps = np.empty_like(ceps) 573 | _gnorm(&ceps[0], &dst_ceps[0], order, gamma) 574 | return dst_ceps 575 | 576 | 577 | def ignorm(np.ndarray[np.float64_t, ndim=1, mode="c"] ceps not None, 578 | gamma=0.0): 579 | assert_gamma(gamma) 580 | cdef int order = len(ceps) - 1 581 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] dst_ceps 582 | dst_ceps = np.empty_like(ceps) 583 | _ignorm(&ceps[0], &dst_ceps[0], order, gamma) 584 | return dst_ceps 585 | 586 | 587 | def freqt(np.ndarray[np.float64_t, ndim=1, mode="c"] ceps not None, 588 | order=25, alpha=0.0): 589 | cdef int src_order = len(ceps) - 1 590 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] dst_ceps 591 | dst_ceps = np.empty(order + 1, dtype=np.float64) 592 | _freqt(&ceps[0], src_order, &dst_ceps[0], order, alpha) 593 | return dst_ceps 594 | 595 | 596 | def frqtr(np.ndarray[np.float64_t, ndim=1, mode="c"] src_ceps not None, 597 | order=25, alpha=0.0): 598 | cdef int src_order = len(src_ceps) - 1 599 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] dst_ceps 600 | dst_ceps = np.empty(order + 1, dtype=np.float64) 601 | _frqtr(&src_ceps[0], src_order, &dst_ceps[0], order, alpha) 602 | return dst_ceps 603 | 604 | 605 | def mgc2mgc(np.ndarray[np.float64_t, ndim=1, mode="c"] src_ceps not None, 606 | src_alpha=0.0, src_gamma=0.0, 607 | dst_order=None, dst_alpha=0.0, dst_gamma=0.0): 608 | assert_gamma(src_gamma) 609 | assert_gamma(dst_gamma) 610 | 611 | cdef int src_order = len(src_ceps) - 1 612 | if dst_order is None: 613 | dst_order = src_order 614 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] dst_ceps 615 | dst_ceps = np.empty(dst_order + 1, dtype=np.float64) 616 | 617 | _mgc2mgc(&src_ceps[0], src_order, src_alpha, src_gamma, 618 | &dst_ceps[0], dst_order, dst_alpha, dst_gamma) 619 | 620 | return dst_ceps 621 | 622 | 623 | @cython.boundscheck(False) 624 | @cython.wraparound(False) 625 | def mgc2sp(np.ndarray[np.float64_t, ndim=1, mode="c"] ceps not None, 626 | alpha=0.0, gamma=0.0, fftlen=256): 627 | assert_gamma(gamma) 628 | assert_fftlen(fftlen) 629 | 630 | cdef int order = len(ceps) - 1 631 | cdef np.ndarray[np.complex128_t, ndim = 1, mode = "c"] sp 632 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] sp_r, sp_i 633 | 634 | sp = np.empty((fftlen >> 1) + 1, dtype=np.complex128) 635 | sp_r = np.zeros(fftlen, dtype=np.float64) 636 | sp_i = np.zeros(fftlen, dtype=np.float64) 637 | 638 | _mgc2sp(&ceps[0], order, alpha, gamma, &sp_r[0], &sp_i[0], fftlen) 639 | 640 | cdef int i 641 | for i in range(0, len(sp)): 642 | sp[i] = sp_r[i] + sp_i[i] * 1j 643 | 644 | return sp 645 | 646 | 647 | def mgclsp2sp(np.ndarray[np.float64_t, ndim=1, mode="c"] lsp not None, 648 | alpha=0.0, gamma=0.0, fftlen=256, gain=True): 649 | assert_gamma(gamma) 650 | assert_fftlen(fftlen) 651 | 652 | cdef int order = gain if len(lsp) - 1 else len(lsp) 653 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] sp 654 | sp = np.empty((fftlen >> 1) + 1, dtype=np.float64) 655 | 656 | _mgclsp2sp(alpha, gamma, &lsp[0], order, &sp[0], len(sp), int(gain)) 657 | 658 | return sp 659 | 660 | 661 | ### F0 analysis ### 662 | 663 | def swipe(np.ndarray[np.float64_t, ndim=1, mode="c"] x not None, 664 | fs, hopsize, 665 | min=60.0, max=240.0, threshold=0.3, otype="f0"): 666 | supported_otypes = ["pitch", "f0", "logf0"] 667 | if isinstance(otype, int) and (not otype in range(0, 3)) or \ 668 | isinstance(otype, str) and not otype in supported_otypes: 669 | raise ValueError("otype must be (0) pitch, (1) f0, or (2) log(f0)") 670 | 671 | if isinstance(otype, str): 672 | otype = supported_otypes.index(otype) 673 | 674 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] f0 675 | cdef int x_length = len(x) 676 | cdef int expected_len = int(np.ceil(float(x_length) / hopsize)) 677 | 678 | f0 = np.empty(expected_len, dtype=np.float64) 679 | 680 | _swipe(&x[0], &f0[0], x_length, fs, hopsize, min, max, threshold, otype) 681 | return f0 682 | 683 | 684 | def rapt(np.ndarray[np.float32_t, ndim=1, mode="c"] x not None, 685 | fs, hopsize, 686 | min=60, max=240, voice_bias=0.0, otype="f0"): 687 | supported_otypes = ["pitch", "f0", "logf0"] 688 | if isinstance(otype, int) and (not otype in range(0, 3)) or \ 689 | isinstance(otype, str) and not otype in supported_otypes: 690 | raise ValueError("otype must be (0) pitch, (1) f0, or (2) log(f0) ") 691 | 692 | if isinstance(otype, str): 693 | otype = supported_otypes.index(otype) 694 | 695 | if min >=max or max >= fs//2 or min <= float(fs)/10000.0: 696 | raise ValueError("invalid min/max frequency parameters") 697 | 698 | frame_period = float(hopsize) / fs 699 | frame_period = float(int(0.5 + (fs * frame_period))) / fs 700 | if frame_period > 0.1 or frame_period < 1.0/fs: 701 | raise ValueError("frame period must be between [1/fs, 0.1]") 702 | 703 | cdef np.ndarray[np.float32_t, ndim = 1, mode = "c"] f0 704 | cdef int x_length = len(x) 705 | cdef int expected_len = int(np.ceil(float(x_length) / hopsize)) 706 | cdef int ret 707 | 708 | f0 = np.empty(expected_len, dtype=np.float32) 709 | 710 | ret = _rapt(&x[0], &f0[0], x_length, fs, hopsize, min, max, 711 | voice_bias, otype) 712 | if ret == 2: 713 | raise ValueError("input range too small for analysis by get_f0") 714 | elif ret == 3: 715 | raise RuntimeError("problem in init_dp_f0()") 716 | 717 | assert ret == 0 718 | 719 | return f0 720 | 721 | 722 | ### Window functions ### 723 | 724 | cdef __window(Window window_type, np.ndarray[np.float64_t, ndim=1, mode="c"] x, 725 | int size, int normalize): 726 | if normalize < 0 or normalize > 2: 727 | raise ValueError("normalize must be 0, 1 or 2") 728 | cdef double g = _window(window_type, &x[0], size, normalize) 729 | return x 730 | 731 | 732 | def blackman(n, normalize=1): 733 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] x 734 | x = np.ones(n, dtype=np.float64) 735 | cdef Window window_type = BLACKMAN 736 | return __window(window_type, x, len(x), normalize) 737 | 738 | 739 | def hamming(n, normalize=1): 740 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] x 741 | x = np.ones(n, dtype=np.float64) 742 | cdef Window window_type = HAMMING 743 | return __window(window_type, x, len(x), normalize) 744 | 745 | 746 | def hanning(n, normalize=1): 747 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] x 748 | x = np.ones(n, dtype=np.float64) 749 | cdef Window window_type = HANNING 750 | return __window(window_type, x, len(x), normalize) 751 | 752 | 753 | def bartlett(n, normalize=1): 754 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] x 755 | x = np.ones(n, dtype=np.float64) 756 | cdef Window window_type = BARTLETT 757 | return __window(window_type, x, len(x), normalize) 758 | 759 | 760 | def trapezoid(n, normalize=1): 761 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] x 762 | x = np.ones(n, dtype=np.float64) 763 | cdef Window window_type = TRAPEZOID 764 | return __window(window_type, x, len(x), normalize) 765 | 766 | 767 | def rectangular(n, normalize=1): 768 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] x 769 | x = np.ones(n, dtype=np.float64) 770 | cdef Window window_type = RECTANGULAR 771 | return __window(window_type, x, len(x), normalize) 772 | 773 | 774 | ### Waveform generation filters ### 775 | 776 | def zerodf_delay_length(int order): 777 | return order 778 | 779 | def zerodf(x, np.ndarray[np.float64_t, ndim=1, mode="c"] a not None, 780 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 781 | cdef int order = len(a) - 1 782 | if len(delay) != zerodf_delay_length(order): 783 | raise ValueError("inconsistent delay length") 784 | 785 | return _zerodf(x, &a[0], order, &delay[0]) 786 | 787 | def zerodft(x, np.ndarray[np.float64_t, ndim=1, mode="c"] a not None, 788 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 789 | cdef int order = len(a) - 1 790 | if len(delay) != zerodf_delay_length(order): 791 | raise ValueError("inconsistent delay length") 792 | 793 | return _zerodft(x, &a[0], order, &delay[0]) 794 | 795 | def poledf_delay_length(int order): 796 | return order 797 | 798 | def poledf(x, np.ndarray[np.float64_t, ndim=1, mode="c"] a not None, 799 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 800 | cdef int order = len(a) - 1 801 | if len(delay) != poledf_delay_length(order): 802 | raise ValueError("inconsistent delay length") 803 | 804 | return _poledf(x, &a[0], order, &delay[0]) 805 | 806 | def poledft(x, np.ndarray[np.float64_t, ndim=1, mode="c"] a not None, 807 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 808 | cdef int order = len(a) - 1 809 | if len(delay) != poledf_delay_length(order): 810 | raise ValueError("inconsistent delay length") 811 | 812 | return _poledft(x, &a[0], order, &delay[0]) 813 | 814 | def lmadf_delay_length(int order, int pd): 815 | return 2 * pd * (order + 1) 816 | 817 | def lmadf(x, np.ndarray[np.float64_t, ndim=1, mode="c"] b not None, 818 | pd, 819 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 820 | assert_pade(pd) 821 | 822 | cdef int order = len(b) - 1 823 | if len(delay) != lmadf_delay_length(order, pd): 824 | raise ValueError("inconsistent delay length") 825 | 826 | return _lmadf(x, &b[0], order, pd, &delay[0]) 827 | 828 | def lspdf_delay_length(int order): 829 | return 2 * order + 1 830 | 831 | def lspdf(x, np.ndarray[np.float64_t, ndim=1, mode="c"] f not None, 832 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 833 | cdef int order = len(f) - 1 834 | if len(delay) != lspdf_delay_length(order): 835 | raise ValueError("inconsistent delay length") 836 | 837 | if order % 2 == 0: 838 | return _lspdf_even(x, &f[0], order, &delay[0]) 839 | else: 840 | return _lspdf_odd(x, &f[0], order, &delay[0]) 841 | 842 | def ltcdf_delay_length(int order): 843 | return order + 1 844 | 845 | def ltcdf(x, np.ndarray[np.float64_t, ndim=1, mode="c"] k not None, 846 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 847 | cdef int order = len(k) - 1 848 | if len(delay) != ltcdf_delay_length(order): 849 | raise ValueError("inconsistent delay length") 850 | 851 | return _ltcdf(x, &k[0], order, &delay[0]) 852 | 853 | def glsadf_delay_length(int order, int stage): 854 | return order * (stage + 1) + 1 855 | 856 | def glsadf(x, np.ndarray[np.float64_t, ndim=1, mode="c"] c not None, 857 | stage, 858 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 859 | assert_stage(stage) 860 | 861 | cdef int order = len(c) - 1 862 | if len(delay) != glsadf_delay_length(order, stage): 863 | raise ValueError("inconsistent delay length") 864 | 865 | return _glsadf(x, &c[0], order, stage, &delay[0]) 866 | 867 | def glsadft(x, np.ndarray[np.float64_t, ndim=1, mode="c"] c not None, 868 | stage, 869 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 870 | assert_stage(stage) 871 | 872 | cdef int order = len(c) - 1 873 | if len(delay) != glsadf_delay_length(order, stage): 874 | raise ValueError("inconsistent delay length") 875 | 876 | return _glsadft(x, &c[0], order, stage, &delay[0]) 877 | 878 | def mlsadf_delay_length(int order, int pd): 879 | return 3 * (pd + 1) + pd * (order + 2) 880 | 881 | def mlsadf(x, np.ndarray[np.float64_t, ndim=1, mode="c"] b not None, 882 | alpha, pd, 883 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 884 | assert_pade(pd) 885 | 886 | cdef int order = len(b) - 1 887 | if len(delay) != mlsadf_delay_length(order, pd): 888 | raise ValueError("inconsistent delay length") 889 | 890 | return _mlsadf(x, &b[0], order, alpha, pd, &delay[0]) 891 | 892 | def mlsadft(x, np.ndarray[np.float64_t, ndim=1, mode="c"] b not None, 893 | alpha, pd, 894 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 895 | assert_pade(pd) 896 | 897 | cdef int order = len(b) - 1 898 | if len(delay) != mlsadf_delay_length(order, pd): 899 | raise ValueError("inconsistent delay length") 900 | 901 | return _mlsadft(x, &b[0], order, alpha, pd, &delay[0]) 902 | 903 | def mglsadf_delay_length(int order, int stage): 904 | return (order + 1) * stage 905 | 906 | def mglsadf(x, np.ndarray[np.float64_t, ndim=1, mode="c"] b not None, 907 | alpha, stage, 908 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 909 | assert_stage(stage) 910 | 911 | cdef int order = len(b) - 1 912 | if len(delay) != mglsadf_delay_length(order, stage): 913 | raise ValueError("inconsistent delay length") 914 | 915 | return _mglsadf(x, &b[0], order, alpha, stage, &delay[0]) 916 | 917 | def mglsadft(x, np.ndarray[np.float64_t, ndim=1, mode="c"] b not None, 918 | alpha, stage, 919 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 920 | assert_stage(stage) 921 | 922 | cdef int order = len(b) - 1 923 | if len(delay) != mglsadf_delay_length(order, stage): 924 | raise ValueError("inconsistent delay length") 925 | 926 | return _mglsadft(x, &b[0], order, alpha, stage, &delay[0]) 927 | 928 | ### Excitation ### 929 | 930 | def excite(np.ndarray[np.float64_t, ndim=1, mode = "c"] pitch, frame_period=100, interp_period=1, gaussian=False, seed=1): 931 | # Allocate memory for output 932 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] excitation 933 | cdef int n = len(pitch) 934 | cdef int expected_len = int(frame_period*(n-1)) 935 | 936 | excitation = np.empty(expected_len, dtype=np.float64) 937 | # Call 938 | _excite(&pitch[0], n, &excitation[0], frame_period, interp_period, gaussian, seed) 939 | # Return allocated output 940 | return excitation 941 | 942 | 943 | ### Utils ### 944 | 945 | def phidf(x, order, alpha, 946 | np.ndarray[np.float64_t, ndim=1, mode="c"] delay not None): 947 | if len(delay) != order + 1: 948 | raise ValueError("inconsistent order or delay") 949 | 950 | _phidf(x, order, alpha, &delay[0]) 951 | 952 | 953 | def lspcheck(np.ndarray[np.float64_t, ndim=1, mode="c"] lsp not None): 954 | cdef int ret = _lspcheck(&lsp[0], len(lsp) - 1) 955 | return ret 956 | 957 | 958 | def levdur(np.ndarray[np.float64_t, ndim=1, mode="c"] r not None, double eps): 959 | cdef int order = len(r) - 1 960 | cdef np.ndarray[np.float64_t, ndim = 1, mode = "c"] a 961 | a = np.empty(order + 1, dtype=np.float64) 962 | cdef int ret = _levdur(&r[0], &a[0], order, eps) 963 | if ret == -1: 964 | raise RuntimeError("abnormally completed") 965 | elif ret == -2: 966 | raise RuntimeError("Unstable LPC") 967 | 968 | return a 969 | -------------------------------------------------------------------------------- /pysptk/conversion.py: -------------------------------------------------------------------------------- 1 | """ 2 | Other conversions 3 | ----------------- 4 | 5 | Not exist in SPTK itself, but can be used with the core API. 6 | Functions in the ``pysptk.conversion`` module can also be directly accesible by ``pysptk.*``. 7 | 8 | .. autosummary:: 9 | :toctree: generated/ 10 | 11 | mgc2b 12 | sp2mc 13 | mc2sp 14 | mc2e 15 | """ 16 | 17 | from __future__ import absolute_import, division, print_function 18 | 19 | import numpy as np 20 | from pysptk.sptk import c2ir, freqt, gnorm, mc2b 21 | from pysptk.util import apply_along_last_axis, automatic_type_conversion 22 | 23 | 24 | @apply_along_last_axis 25 | @automatic_type_conversion 26 | def mgc2b(mgc, alpha=0.35, gamma=0.0): 27 | """Mel-generalized cepstrum to MGLSA filter coefficients 28 | 29 | Parameters 30 | ---------- 31 | mgc : array, shape 32 | Mel-generalized cepstrum 33 | 34 | alpha : float 35 | All-pass constant. Default is 0.35. 36 | 37 | gamma : float 38 | Parameter of generalized log function. Default is 0.0. 39 | 40 | Returns 41 | ------- 42 | b : array, shape(same as ``mgc``) 43 | MGLSA filter coefficients 44 | 45 | See Also 46 | -------- 47 | pysptk.sptk.mlsadf 48 | pysptk.sptk.mglsadf 49 | pysptk.sptk.mc2b 50 | pysptk.sptk.b2mc 51 | pysptk.sptk.mcep 52 | pysptk.sptk.mgcep 53 | 54 | """ 55 | 56 | b = mc2b(mgc, alpha) 57 | if gamma == 0: 58 | return b 59 | 60 | b = gnorm(b, gamma) 61 | 62 | b[0] = np.log(b[0]) 63 | b[1:] *= gamma 64 | 65 | return b 66 | 67 | 68 | @apply_along_last_axis 69 | @automatic_type_conversion 70 | def sp2mc(powerspec, order, alpha): 71 | """Convert spectrum envelope to mel-cepstrum 72 | 73 | This is a simplified implementation of ``mcep`` for input type 74 | is 4. 75 | 76 | Parameters 77 | ---------- 78 | powerspec : array 79 | Power spectrum 80 | 81 | order : int 82 | Order of mel-cepstrum 83 | 84 | alpha : float 85 | All-pass constant. 86 | 87 | Returns 88 | ------- 89 | mc : array, shape(``order+1``) 90 | mel-cepstrum 91 | 92 | See Also 93 | -------- 94 | pysptk.sptk.mcep 95 | pysptk.conversion.mc2sp 96 | 97 | """ 98 | 99 | # |X(ω)|² -> log(|X(ω)²|) 100 | logperiodogram = np.log(powerspec) 101 | 102 | # transform log-periodogram to real cepstrum 103 | # log(|X(ω)|²) -> c(m) 104 | c = np.fft.irfft(logperiodogram) 105 | c[0] /= 2.0 106 | 107 | # c(m) -> cₐ(m) 108 | return freqt(c, order, alpha) 109 | 110 | 111 | @apply_along_last_axis 112 | @automatic_type_conversion 113 | def mc2sp(mc, alpha, fftlen): 114 | """Convert mel-cepstrum back to power spectrum 115 | 116 | Parameters 117 | ---------- 118 | mc : array 119 | Mel-spectrum 120 | 121 | alpha : float 122 | All-pass constant. 123 | 124 | fftlen : int 125 | FFT length 126 | 127 | Returns 128 | ------- 129 | powerspec : array, shape(``fftlen//2 +1``) 130 | Power spectrum 131 | 132 | See Also 133 | -------- 134 | pysptk.sptk.mcep 135 | pysptk.conversion.sp2mc 136 | 137 | """ 138 | # back to cepstrum from mel-cesptrum 139 | # cₐ(m) -> c(m) 140 | c = freqt(mc, int(fftlen // 2), -alpha) 141 | c[0] *= 2.0 142 | 143 | symc = np.zeros(fftlen) 144 | symc[0] = c[0] 145 | for i in range(1, len(c)): 146 | symc[i] = c[i] 147 | symc[-i] = c[i] 148 | 149 | # back to power spectrum 150 | # c(m) -> log(|X(ω)|²) -> |X(ω)|² 151 | return np.exp(np.fft.rfft(symc).real) 152 | 153 | 154 | @apply_along_last_axis 155 | @automatic_type_conversion 156 | def mc2e(mc, alpha=0.35, irlen=256): 157 | """Compute energy from mel-cepstrum 158 | 159 | Inspired from hts_engine 160 | 161 | Parameters 162 | ---------- 163 | mc : array 164 | Mel-spectrum 165 | 166 | alpha : float 167 | All-pass constant. 168 | 169 | irlen : int 170 | IIR filter length 171 | 172 | Returns 173 | ------- 174 | energy : floating point, scalar 175 | frame energy 176 | """ 177 | # back to linear frequency domain 178 | c = freqt(mc, irlen - 1, -alpha) 179 | 180 | # compute impule response from cepsturm 181 | ir = c2ir(c, irlen) 182 | 183 | return np.sum(np.abs(ir * ir)) 184 | -------------------------------------------------------------------------------- /pysptk/example_audio_data/COPYING: -------------------------------------------------------------------------------- 1 | 2 | This voice is free for use for any purpose (commercial or otherwise) 3 | subject to the pretty light restrictions detailed below. 4 | 5 | ############################################################################ 6 | ### ## 7 | ### Carnegie Mellon University ## 8 | ### Copyright (c) 2003 ## 9 | ### All Rights Reserved. ## 10 | ### ## 11 | ### Permission to use, copy, modify, and licence this software and its ## 12 | ### documentation for any purpose, is hereby granted without fee, ## 13 | ### subject to the following conditions: ## 14 | ### 1. The code must retain the above copyright notice, this list of ## 15 | ### conditions and the following disclaimer. ## 16 | ### 2. Any modifications must be clearly marked as such. ## 17 | ### 3. Original authors' names are not deleted. ## 18 | ### ## 19 | ### THE AUTHORS OF THIS WORK DISCLAIM ALL WARRANTIES WITH REGARD TO ## 20 | ### THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ## 21 | ### AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY ## 22 | ### SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ## 23 | ### WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN ## 24 | ### AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ## 25 | ### ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF ## 26 | ### THIS SOFTWARE. ## 27 | ### ## 28 | ############################################################################ 29 | ### ## 30 | ### See http://www.festvox.org/cmu_arctic/ for more details ## 31 | ### ## 32 | ############################################################################ 33 | 34 | -------------------------------------------------------------------------------- /pysptk/example_audio_data/arctic_a0007.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r9y9/pysptk/65c26f5cac3caf8af031ef100c53369c3c83c5ef/pysptk/example_audio_data/arctic_a0007.wav -------------------------------------------------------------------------------- /pysptk/synthesis.py: -------------------------------------------------------------------------------- 1 | """ 2 | High-level interface for waveform synthesis 3 | =========================================== 4 | 5 | Module ``pysptk.synthesis`` provides high-leve interface that wraps low-level 6 | SPTK waveform synthesis functions (e.g. ``mlsadf``), 7 | 8 | Synthesis filter interface 9 | -------------------------- 10 | 11 | .. autoclass:: SynthesisFilter 12 | :members: 13 | 14 | Synthesizer 15 | ----------- 16 | .. autoclass:: Synthesizer 17 | :members: 18 | 19 | SynthesisFilters 20 | ---------------- 21 | 22 | LMADF 23 | ^^^^^ 24 | .. autoclass:: LMADF 25 | :members: 26 | 27 | MLSADF 28 | ^^^^^^ 29 | .. autoclass:: MLSADF 30 | :members: 31 | 32 | GLSADF 33 | ^^^^^^ 34 | .. autoclass:: GLSADF 35 | :members: 36 | 37 | MGLSADF 38 | ^^^^^^^ 39 | .. autoclass:: MGLSADF 40 | :members: 41 | 42 | AllZeroDF 43 | ^^^^^^^^^ 44 | .. autoclass:: AllZeroDF 45 | :members: 46 | 47 | AllPoleDF 48 | ^^^^^^^^^ 49 | .. autoclass:: AllPoleDF 50 | :members: 51 | 52 | AllPoleLatticeDF 53 | ^^^^^^^^^^^^^^^^ 54 | .. autoclass:: AllPoleLatticeDF 55 | :members: 56 | 57 | """ 58 | 59 | from abc import abstractmethod 60 | 61 | import numpy as np 62 | import pysptk 63 | from pysptk.util import assert_pade, assert_stage 64 | 65 | 66 | class SynthesisFilter(object): 67 | """Synthesis filter interface 68 | 69 | All synthesis filters must implement this interface. 70 | """ 71 | 72 | @abstractmethod 73 | def filt(self, x, coef): 74 | """Filter one sample 75 | 76 | Parameters 77 | ---------- 78 | x : float 79 | A input sample 80 | 81 | coef : array 82 | Filter coefficients 83 | 84 | Returns 85 | ------- 86 | y : float 87 | A filtered sample 88 | 89 | """ 90 | 91 | def filtt(self, x, coef): 92 | """Transpose filter 93 | 94 | Can be optional. 95 | 96 | Parameters 97 | ---------- 98 | x : float 99 | A input sample 100 | 101 | coef : array 102 | Filter coefficients 103 | 104 | Returns 105 | ------- 106 | y : float 107 | A filtered sample 108 | 109 | """ 110 | raise NotImplementedError() 111 | 112 | 113 | class Synthesizer(object): 114 | """Speech waveform synthesizer 115 | 116 | 117 | Attributes 118 | ---------- 119 | filt : SynthesisFilter 120 | A speech synthesis filter 121 | 122 | hopsize : int 123 | Hop size 124 | 125 | transpose : bool 126 | Transpose filter or not. Default is False. 127 | 128 | """ 129 | 130 | def __init__(self, filt, hopsize, transpose=False): 131 | """Initialization 132 | 133 | Raises 134 | ------ 135 | TypeError 136 | if ``filt`` is not a instance of ``SynthesisFilter`` 137 | 138 | """ 139 | if not isinstance(filt, SynthesisFilter): 140 | raise TypeError("filt must be an instance of SynthesisFilter") 141 | 142 | self.filt = filt 143 | self.hopsize = hopsize 144 | self.transpose = transpose 145 | 146 | def synthesis_one_frame(self, source, prev_b, curr_b): 147 | """Synthesize one frame waveform 148 | 149 | Parameters 150 | ---------- 151 | source : array 152 | Source excitation 153 | 154 | prev_b : array 155 | Filter coefficients of previous frame 156 | 157 | curr_b : array 158 | Filter coefficients of current frame 159 | 160 | Returns 161 | ------- 162 | y : array 163 | Synthesized waveform 164 | 165 | """ 166 | assert len(prev_b) == len(curr_b) 167 | slope = (curr_b - prev_b) / len(source) 168 | interpolated_coef = prev_b.copy() 169 | 170 | y = np.empty_like(source) 171 | 172 | # filter function 173 | filt = self.filt.filtt if self.transpose else self.filt.filt 174 | 175 | for i in range(len(source)): 176 | scaled_source = source[i] * np.exp(interpolated_coef[0]) 177 | y[i] = filt(scaled_source, interpolated_coef) 178 | interpolated_coef += slope 179 | 180 | return y 181 | 182 | def synthesis(self, source, b): 183 | """Synthesize a waveform given a source excitation and sequence of 184 | filter coefficients (e.g. cepstrum). 185 | 186 | Parameters 187 | ---------- 188 | source : array 189 | Source excitation 190 | 191 | b : array 192 | Filter coefficients 193 | 194 | Returns 195 | ------- 196 | y : array, shape (same as ``source``) 197 | Synthesized waveform 198 | 199 | """ 200 | 201 | y = np.zeros_like(source) 202 | 203 | b_prev = b[0, :] 204 | b_curr = b_prev 205 | for i in range(b.shape[0]): 206 | if i > 0: 207 | b_prev = b[i - 1, :] 208 | b_curr = b[i, :] 209 | 210 | s, e = i * self.hopsize, (i + 1) * self.hopsize 211 | if e > len(source): 212 | break 213 | 214 | y[s:e] = self.synthesis_one_frame(source[s:e], b_prev, b_curr) 215 | 216 | return y 217 | 218 | 219 | class LMADF(SynthesisFilter): 220 | """LMA digital filter that wraps ``lmadf`` 221 | 222 | Attributes 223 | ---------- 224 | pd : int 225 | Order of pade approximation. Default is 4. 226 | 227 | delay : array 228 | Delay 229 | 230 | """ 231 | 232 | def __init__(self, order=25, pd=4): 233 | """Initialization 234 | 235 | Raises 236 | ====== 237 | ValueError 238 | if invalid order of pade approximation is specified 239 | 240 | """ 241 | self.order = order 242 | 243 | assert_pade(pd) 244 | 245 | self.pd = pd 246 | self.delay = pysptk.lmadf_delay(order, pd) 247 | 248 | def filt(self, x, coef): 249 | """Filter one sample using ``lmadf`` 250 | 251 | Parameters 252 | ---------- 253 | x : float 254 | A input sample 255 | 256 | coef: array 257 | LMA filter coefficients (i.e. Cepstrum) 258 | 259 | Returns 260 | ------- 261 | y : float 262 | A filtered sample 263 | 264 | See Also 265 | -------- 266 | pysptk.sptk.lmadf 267 | 268 | """ 269 | 270 | return pysptk.lmadf(x, coef, self.pd, self.delay) 271 | 272 | 273 | class MLSADF(SynthesisFilter): 274 | """MLSA digital filter that wraps ``mlsadf`` 275 | 276 | Attributes 277 | ---------- 278 | alpha : float 279 | All-pass constant 280 | 281 | pd : int 282 | Order of pade approximation. Default is 4. 283 | 284 | delay : array 285 | Delay 286 | 287 | """ 288 | 289 | def __init__(self, order=25, alpha=0.35, pd=4): 290 | """Initialization 291 | 292 | Raises 293 | ====== 294 | ValueError 295 | if invalid order of pade approximation is specified 296 | 297 | """ 298 | 299 | self.order = order 300 | 301 | assert_pade(pd) 302 | 303 | self.alpha = alpha 304 | self.pd = pd 305 | self.delay = pysptk.mlsadf_delay(order, pd) 306 | 307 | def filt(self, x, coef): 308 | """Filter one sample using ``mlsadf`` 309 | 310 | Parameters 311 | ---------- 312 | x : float 313 | A input sample 314 | 315 | coef: array 316 | MLSA filter coefficients 317 | 318 | Returns 319 | ------- 320 | y : float 321 | A filtered sample 322 | 323 | See Also 324 | -------- 325 | pysptk.sptk.mlsadf 326 | pysptk.sptk.mc2b 327 | 328 | """ 329 | return pysptk.mlsadf(x, coef, self.alpha, self.pd, self.delay) 330 | 331 | def filtt(self, x, coef): 332 | """Transpose filter using ``mlsadft`` 333 | 334 | Parameters 335 | ---------- 336 | x : float 337 | A input sample 338 | 339 | coef: array 340 | MLSA filter coefficients 341 | 342 | Returns 343 | ------- 344 | y : float 345 | A filtered sample 346 | 347 | See Also 348 | -------- 349 | pysptk.sptk.mlsadft 350 | """ 351 | return pysptk.mlsadft(x, coef, self.alpha, self.pd, self.delay) 352 | 353 | 354 | class GLSADF(SynthesisFilter): 355 | """GLSA digital filter that wraps ``glsadf`` 356 | 357 | Attributes 358 | ---------- 359 | stage : int 360 | -1/gamma 361 | 362 | delay : array 363 | Delay 364 | 365 | """ 366 | 367 | def __init__(self, order=25, stage=1): 368 | """Initialization 369 | 370 | Raises 371 | ------ 372 | ValueError 373 | if invalid number of stage is specified 374 | 375 | """ 376 | self.order = order 377 | 378 | assert_stage(stage) 379 | 380 | self.stage = stage 381 | self.delay = pysptk.glsadf_delay(order, stage) 382 | 383 | def filt(self, x, coef): 384 | """Filter one sample using ``glsadf`` 385 | 386 | Parameters 387 | ---------- 388 | x : float 389 | A input sample 390 | 391 | coef: array 392 | GLSA filter coefficients 393 | 394 | Returns 395 | ------- 396 | y : float 397 | A filtered sample 398 | 399 | See Also 400 | -------- 401 | pysptk.sptk.glsadf 402 | """ 403 | return pysptk.glsadf(x, coef, self.stage, self.delay) 404 | 405 | def filtt(self, x, coef): 406 | """Filter one sample using ``glsadft`` 407 | 408 | Parameters 409 | ---------- 410 | x : float 411 | A input sample 412 | 413 | coef: array 414 | GLSA filter coefficients 415 | 416 | Returns 417 | ------- 418 | y : float 419 | A filtered sample 420 | 421 | See Also 422 | -------- 423 | pysptk.sptk.glsadft 424 | """ 425 | return pysptk.glsadft(x, coef, self.stage, self.delay) 426 | 427 | 428 | class MGLSADF(SynthesisFilter): 429 | """MGLSA digital filter that wraps ``mglsadf`` 430 | 431 | Attributes 432 | ---------- 433 | alpha : float 434 | All-pass constant 435 | 436 | stage : int 437 | -1/gamma 438 | 439 | delay : array 440 | Delay 441 | 442 | """ 443 | 444 | def __init__(self, order=25, alpha=0.35, stage=1): 445 | """Initialization 446 | 447 | Raises 448 | ------ 449 | ValueError 450 | if invalid number of stage is specified 451 | 452 | """ 453 | self.order = order 454 | 455 | assert_stage(stage) 456 | 457 | self.alpha = alpha 458 | self.stage = stage 459 | self.delay = pysptk.mglsadf_delay(order, stage) 460 | 461 | def filt(self, x, coef): 462 | """Filter one sample using ``mglsadf`` 463 | 464 | Parameters 465 | ---------- 466 | x : float 467 | A input sample 468 | 469 | coef: array 470 | MGLSA filter coefficients 471 | 472 | Returns 473 | ------- 474 | y : float 475 | A filtered sample 476 | 477 | See Also 478 | -------- 479 | pysptk.sptk.mglsadf 480 | """ 481 | return pysptk.mglsadf(x, coef, self.alpha, self.stage, self.delay) 482 | 483 | def filtt(self, x, coef): 484 | """Filter one sample using ``mglsadft`` 485 | 486 | Parameters 487 | ---------- 488 | x : float 489 | A input sample 490 | 491 | coef: array 492 | MGLSA filter coefficients 493 | 494 | Returns 495 | ------- 496 | y : float 497 | A filtered sample 498 | 499 | See Also 500 | -------- 501 | pysptk.sptk.mglsadft 502 | """ 503 | return pysptk.mglsadft(x, coef, self.alpha, self.stage, self.delay) 504 | 505 | 506 | class AllZeroDF(SynthesisFilter): 507 | """All-zero digital filter that wraps ``zerodf`` 508 | 509 | Attributes 510 | ---------- 511 | delay : array 512 | Delay 513 | 514 | """ 515 | 516 | def __init__(self, order=25): 517 | """Initialization""" 518 | 519 | self.order = order 520 | self.delay = pysptk.zerodf_delay(order) 521 | 522 | def filt(self, x, coef): 523 | """Filter one sample using using ``zerodf`` 524 | 525 | Parameters 526 | ---------- 527 | x : float 528 | A input sample 529 | 530 | coef: array 531 | FIR parameters 532 | _ 533 | Returns 534 | ------- 535 | y : float 536 | A filtered sample 537 | 538 | See Also 539 | -------- 540 | pysptk.sptk.zerodf 541 | """ 542 | return pysptk.zerodf(x, coef, self.delay) 543 | 544 | def filtt(self, x, coef): 545 | """Filter one sample using using ``zerodft`` 546 | 547 | Parameters 548 | ---------- 549 | x : float 550 | A input sample 551 | 552 | coef: array 553 | FIR parameters 554 | 555 | Returns 556 | ------- 557 | y : float 558 | A filtered sample 559 | 560 | See Also 561 | -------- 562 | pysptk.sptk.zerodft 563 | """ 564 | return pysptk.zerodf(x, coef, self.delay) 565 | 566 | 567 | class AllPoleDF(SynthesisFilter): 568 | """All-pole digital filter that wraps ``poledf`` 569 | 570 | Attributes 571 | ---------- 572 | delay : array 573 | Delay 574 | 575 | """ 576 | 577 | def __init__(self, order=25): 578 | """Initialization""" 579 | 580 | self.order = order 581 | self.delay = pysptk.poledf_delay(order) 582 | 583 | def filt(self, x, coef): 584 | """Filter one sample using using ``poledf`` 585 | 586 | Parameters 587 | ---------- 588 | x : float 589 | A input sample 590 | 591 | coef: array 592 | LPC (with loggain) 593 | 594 | Returns 595 | ------- 596 | y : float 597 | A filtered sample 598 | 599 | See Also 600 | -------- 601 | pysptk.sptk.poledf 602 | """ 603 | return pysptk.poledf(x, coef, self.delay) 604 | 605 | def filtt(self, x, coef): 606 | """Filter one sample using using ``poledft`` 607 | 608 | Parameters 609 | ---------- 610 | x : float 611 | A input sample 612 | 613 | coef: array 614 | LPC (with loggain) 615 | 616 | Returns 617 | ------- 618 | y : float 619 | A filtered sample 620 | 621 | See Also 622 | -------- 623 | pysptk.sptk.poledft 624 | """ 625 | return pysptk.poledf(x, coef, self.delay) 626 | 627 | 628 | class AllPoleLatticeDF(SynthesisFilter): 629 | """All-pole lttice digital filter that wraps ``ltcdf`` 630 | 631 | Attributes 632 | ---------- 633 | delay : array 634 | Delay 635 | 636 | """ 637 | 638 | def __init__(self, order=25): 639 | """Initialization""" 640 | 641 | self.order = order 642 | self.delay = pysptk.ltcdf_delay(order) 643 | 644 | def filt(self, x, coef): 645 | """Filter one sample using using ``ltcdf`` 646 | 647 | Parameters 648 | ---------- 649 | x : float 650 | A input sample 651 | 652 | coef: array 653 | PARCOR coefficients (with loggain) 654 | 655 | Returns 656 | ------- 657 | y : float 658 | A filtered sample 659 | 660 | See Also 661 | -------- 662 | pysptk.sptk.ltcdf 663 | 664 | """ 665 | 666 | return pysptk.ltcdf(x, coef, self.delay) 667 | 668 | 669 | class LSPDF(SynthesisFilter): 670 | """All-pole digital filter that wraps ``lspdf`` 671 | 672 | Attributes 673 | ---------- 674 | delay : array 675 | Delay 676 | 677 | """ 678 | 679 | def __init__(self, order=25): 680 | """Initialization""" 681 | 682 | self.order = order 683 | self.delay = pysptk.lspdf_delay(order) 684 | 685 | def filt(self, x, coef): 686 | """Filter one sample using using ``lspdf`` 687 | 688 | Parameters 689 | ---------- 690 | x : float 691 | A input sample 692 | 693 | coef: array 694 | LSP (with loggain) 695 | 696 | Returns 697 | ------- 698 | y : float 699 | A filtered sample 700 | 701 | See Also 702 | -------- 703 | pysptk.sptk.lspdf 704 | 705 | """ 706 | 707 | return pysptk.lspdf(x, coef, self.delay) 708 | -------------------------------------------------------------------------------- /pysptk/util.py: -------------------------------------------------------------------------------- 1 | """ 2 | Utilities 3 | ========= 4 | 5 | Audio files 6 | ----------- 7 | 8 | .. autosummary:: 9 | :toctree: generated/ 10 | 11 | example_audio_file 12 | 13 | 14 | Mel-cepstrum analysis 15 | --------------------- 16 | 17 | .. autosummary:: 18 | :toctree: generated/ 19 | 20 | mcepalpha 21 | """ 22 | 23 | # I originally tried with functools.wraps to create decoraters, but it didn't 24 | # work to me if I use multiple decoratores to decorate a function. 25 | # Specifically, I cannot inspect argspec with a decorated function, so cannot 26 | # get a argment name simply from it. As suggested in the following 27 | # stackoverflow thread, using decorator package. 28 | # https://stackoverflow.com/questions/12558505/preserve-argspec-when-decorating 29 | from inspect import getfullargspec 30 | 31 | import numpy as np 32 | import pkg_resources 33 | from decorator import decorator 34 | 35 | # 16kHz, 16bit example audio from cmu_us_awb_arctic 36 | # see COPYING for the license of the audio file. 37 | EXAMPLE_AUDIO = "example_audio_data/arctic_a0007.wav" 38 | 39 | 40 | @decorator 41 | def apply_along_last_axis(func, *args, **kwargs): 42 | """Apply function along last axis 43 | 44 | This is used for extending vector-to-vector operations to matrix-to-matrix 45 | operations. This basically does the following thing in a convenient way: 46 | 47 | ```py 48 | np.apply_along_axis(func, input_vector, -1, *args, **kwargs) 49 | ``` 50 | 51 | Note: The decorator assumes that the first argment of the function is the 52 | input vector (1d numpy array). 53 | """ 54 | 55 | # Get first arg 56 | first_arg_name = getfullargspec(func)[0][0] 57 | has_positional_arg = len(args) > 0 58 | input_arg = args[0] if has_positional_arg else kwargs[first_arg_name] 59 | 60 | if input_arg.ndim == 1: 61 | ret = func(*args, **kwargs) 62 | else: 63 | # we need at least 1 positonal argment 64 | if len(args) == 0: 65 | args = kwargs.pop(first_arg_name) 66 | ret = np.apply_along_axis(func, -1, *args, **kwargs) 67 | 68 | return ret 69 | 70 | 71 | @decorator 72 | def automatic_type_conversion(func, *args, **kwargs): 73 | first_arg_name = getfullargspec(func)[0][0] 74 | has_positional_arg = len(args) > 0 75 | input_arg = args[0] if has_positional_arg else kwargs[first_arg_name] 76 | dtypein = input_arg.dtype 77 | 78 | # Since C functions can only accept double 79 | if dtypein != np.float64: 80 | if has_positional_arg: 81 | args = tuple( 82 | map( 83 | lambda v: input_arg.astype(np.float64) if v[0] == 0 else v[1], 84 | enumerate(args), 85 | ) 86 | ) 87 | else: 88 | kwargs[first_arg_name] = input_arg.astype(np.float64) 89 | return func(*args, **kwargs).astype(dtypein) 90 | 91 | 92 | @decorator 93 | def automatic_type_conversion_float32(func, *args, **kwargs): 94 | first_arg_name = getfullargspec(func)[0][0] 95 | has_positional_arg = len(args) > 0 96 | input_arg = args[0] if has_positional_arg else kwargs[first_arg_name] 97 | dtypein = input_arg.dtype 98 | 99 | if dtypein != np.float32: 100 | if has_positional_arg: 101 | args = tuple( 102 | map( 103 | lambda v: input_arg.astype(np.float32) if v[0] == 0 else v[1], 104 | enumerate(args), 105 | ) 106 | ) 107 | else: 108 | kwargs[first_arg_name] = input_arg.astype(np.float32) 109 | return func(*args, **kwargs).astype(dtypein) 110 | 111 | 112 | def assert_gamma(gamma): 113 | if not (-1 <= gamma <= 0.0): 114 | raise ValueError("unsupported gamma: must be -1 <= gamma <= 0") 115 | 116 | 117 | def assert_pade(pade): 118 | valid = [4, 5, 6, 7] 119 | if pade not in valid: 120 | raise ValueError("4, 5, 6 or 7 pade approximation is supported") 121 | 122 | 123 | def assert_stage(stage): 124 | if stage < 1: 125 | raise ValueError("stage >= 1 (-1 <= gamma < 0)") 126 | 127 | 128 | def ispow2(num): 129 | return ((num & (num - 1)) == 0) and num != 0 130 | 131 | 132 | def assert_fftlen(fftlen): 133 | if not ispow2(fftlen): 134 | raise ValueError("fftlen must be power of 2") 135 | 136 | 137 | def example_audio_file(): 138 | """Get the path to an included audio example file. 139 | 140 | Examples 141 | -------- 142 | >>> from scipy.io import wavfile 143 | >>> fs, x = wavfile.read(pysptk.util.example_audio_file()) 144 | 145 | >>> import matplotlib.pyplot as plt 146 | >>> plt.plot(x, label="cmu_us_awb_arctic arctic_a0007.wav") 147 | >>> plt.xlim(0, len(x)) 148 | >>> plt.legend() 149 | 150 | """ 151 | 152 | return pkg_resources.resource_filename(__name__, EXAMPLE_AUDIO) 153 | 154 | 155 | def mcepalpha(fs, start=0.0, stop=1.0, step=0.001, num_points=1000): 156 | """Compute appropriate frequency warping parameter given a sampling frequency 157 | 158 | It would be useful to determine alpha parameter in mel-cepstrum analysis. 159 | 160 | The code is traslated from https://bitbucket.org/happyalu/mcep_alpha_calc. 161 | 162 | Parameters 163 | ---------- 164 | fs : int 165 | Sampling frequency 166 | 167 | start : float 168 | start value that will be passed to numpy.arange. Default is 0.0. 169 | 170 | stop : float 171 | stop value that will be passed to numpy.arange. Default is 1.0. 172 | 173 | step : float 174 | step value that will be passed to numpy.arange. Default is 0.001. 175 | 176 | num_points : int 177 | Number of points used in approximating mel-scale vectors in fixed- 178 | length. 179 | 180 | Returns 181 | ------- 182 | alpha : float 183 | frequency warping paramter (offen denoted by alpha) 184 | 185 | See Also 186 | -------- 187 | pysptk.sptk.mcep 188 | pysptk.sptk.mgcep 189 | 190 | """ 191 | alpha_candidates = np.arange(start, stop, step) 192 | mel = _melscale_vector(fs, num_points) 193 | distances = [ 194 | rms_distance(mel, _warping_vector(alpha, num_points)) 195 | for alpha in alpha_candidates 196 | ] 197 | return alpha_candidates[np.argmin(distances)] 198 | 199 | 200 | def _melscale_vector(fs, length): 201 | step = (fs / 2.0) / length 202 | melscalev = 1000.0 / np.log(2) * np.log(1 + step * np.arange(0, length) / 1000.0) 203 | return melscalev / melscalev[-1] 204 | 205 | 206 | def _warping_vector(alpha, length): 207 | step = np.pi / length 208 | omega = step * np.arange(0, length) 209 | num = (1 - alpha * alpha) * np.sin(omega) 210 | den = (1 + alpha * alpha) * np.cos(omega) - 2 * alpha 211 | warpfreq = np.arctan(num / den) 212 | warpfreq[warpfreq < 0] += np.pi 213 | return warpfreq / warpfreq[-1] 214 | 215 | 216 | def rms_distance(v1, v2): 217 | d = v1 - v2 218 | return np.sum(np.abs(d * d)) / len(v1) 219 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script for Pypi release 4 | # 0. Make sure you are on git tag 5 | # 1. Run the script 6 | # 2. Upload sdist 7 | 8 | set -e 9 | 10 | script_dir=$(cd $(dirname ${BASH_SOURCE:-$0}); pwd) 11 | cd $script_dir 12 | 13 | TAG=$(git describe --exact-match --tags HEAD) 14 | 15 | VERSION=${TAG/v/} 16 | 17 | PYSPTK_BUILD_VERSION=$VERSION python setup.py develop sdist 18 | echo "*** Ready to release! pysptk $TAG ***" 19 | echo "Please make sure that release verion is correct." 20 | cat pysptk/version.py 21 | echo "Please run the following command manually:" 22 | echo twine upload dist/pysptk-${VERSION}.tar.gz --repository-url https://upload.pypi.org/legacy/ 23 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | from distutils.version import LooseVersion 4 | from glob import glob 5 | from os.path import join 6 | 7 | import setuptools.command.build_py 8 | import setuptools.command.develop 9 | from setuptools import Extension, find_packages, setup 10 | 11 | version = "1.0.2-dev" 12 | 13 | # Adapted from https://github.com/py_torch/pytorch 14 | cwd = os.path.dirname(os.path.abspath(__file__)) 15 | if os.getenv("PYSPTK_BUILD_VERSION"): 16 | version = os.getenv("PYSPTK_BUILD_VERSION") 17 | else: 18 | try: 19 | sha = ( 20 | subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=cwd) 21 | .decode("ascii") 22 | .strip() 23 | ) 24 | version += "+" + sha[:7] 25 | except subprocess.CalledProcessError: 26 | pass 27 | except IOError: # FileNotFoundError for python 3 28 | pass 29 | 30 | 31 | class build_py(setuptools.command.build_py.build_py): 32 | def run(self): 33 | self.create_version_file() 34 | setuptools.command.build_py.build_py.run(self) 35 | 36 | @staticmethod 37 | def create_version_file(): 38 | global version, cwd 39 | print("-- Building version " + version) 40 | version_path = os.path.join(cwd, "pysptk", "version.py") 41 | with open(version_path, "w") as f: 42 | f.write("__version__ = '{}'\n".format(version)) 43 | 44 | 45 | class develop(setuptools.command.develop.develop): 46 | def run(self): 47 | build_py.create_version_file() 48 | setuptools.command.develop.develop.run(self) 49 | 50 | 51 | cmdclass = {"build_py": build_py, "develop": develop} 52 | 53 | min_cython_ver = "0.28.0" 54 | try: 55 | import Cython 56 | 57 | ver = Cython.__version__ 58 | _CYTHON_INSTALLED = ver >= LooseVersion(min_cython_ver) 59 | except ImportError: 60 | _CYTHON_INSTALLED = False 61 | 62 | try: 63 | if not _CYTHON_INSTALLED: 64 | raise ImportError("No supported version of Cython installed.") 65 | from Cython.Distutils import build_ext 66 | 67 | cython = True 68 | except ImportError: 69 | cython = False 70 | from setuptools.command.build_ext import build_ext as _build_ext 71 | 72 | class build_ext(_build_ext): 73 | # https://stackoverflow.com/questions/19919905/how-to-bootstrap-numpy-installation-in-setup-py # noqa 74 | def finalize_options(self): 75 | _build_ext.finalize_options(self) 76 | # Prevent numpy from thinking it is still in its setup process: 77 | __builtins__.__NUMPY_SETUP__ = False 78 | import numpy 79 | 80 | self.include_dirs.append(numpy.get_include()) 81 | 82 | 83 | include_dirs = [join(os.getcwd(), "lib", "SPTK", "include")] 84 | cmdclass["build_ext"] = build_ext 85 | if cython: 86 | ext = ".pyx" 87 | import numpy as np 88 | 89 | include_dirs.insert(0, np.get_include()) 90 | else: 91 | ext = ".c" 92 | if not os.path.exists(join("pysptk", "_sptk" + ext)): 93 | raise RuntimeError("Cython is required to generate C code.") 94 | 95 | # SPTK sources 96 | src_top = join("lib", "SPTK") 97 | src_bin_top = join(src_top, "bin") 98 | swipe_src = [ 99 | join(src_bin_top, "pitch", "swipe", "swipe.c"), 100 | join(src_bin_top, "pitch", "swipe", "vector.c"), 101 | ] 102 | rapt_src = [ 103 | join(src_bin_top, "pitch", "snack", "jkGetF0.c"), 104 | join(src_bin_top, "pitch", "snack", "sigproc.c"), 105 | ] 106 | 107 | sptklib_src = glob(join(src_top, "lib", "*.c")) 108 | sptk_src = glob(join(src_bin_top, "*", "_*.c")) 109 | 110 | # collect all sources 111 | sptk_all_src = sptk_src + sptklib_src + swipe_src + rapt_src 112 | 113 | # Filter ignore list 114 | ignore_bin_list = [ 115 | join(src_bin_top, "wavjoin"), 116 | join(src_bin_top, "wavsplit"), 117 | join(src_bin_top, "vc"), 118 | ] 119 | for ignore in ignore_bin_list: 120 | sptk_all_src = list(filter(lambda s, ig=ignore: not s.startswith(ig), sptk_all_src)) 121 | 122 | # define core cython module 123 | ext_modules = [ 124 | Extension( 125 | name="pysptk._sptk", 126 | sources=[join("pysptk", "_sptk" + ext)] + sptk_all_src, 127 | include_dirs=include_dirs, 128 | language="c", 129 | extra_compile_args=["-std=c99"], 130 | ) 131 | ] 132 | 133 | with open("README.md", "r") as fh: 134 | LONG_DESC = fh.read() 135 | 136 | setup( 137 | name="pysptk", 138 | version=version, 139 | description="A python wrapper for Speech Signal Processing Toolkit (SPTK)", 140 | long_description=LONG_DESC, 141 | long_description_content_type="text/markdown", 142 | author="Ryuichi Yamamoto", 143 | author_email="zryuichi@gmail.com", 144 | url="https://github.com/r9y9/pysptk", 145 | license="MIT", 146 | packages=find_packages(exclude=["tests", "examples"]), 147 | package_data={"": ["example_audio_data/*"]}, 148 | ext_modules=ext_modules, 149 | cmdclass=cmdclass, 150 | setup_requires=["numpy >= 1.20.0"], 151 | install_requires=[ 152 | "scipy", 153 | "decorator", 154 | "cython >= " + min_cython_ver, 155 | ], 156 | tests_require=["pytest", "pytest-cov", "coverage"], 157 | extras_require={ 158 | "docs": ["numpydoc", "sphinx_rtd_theme", "seaborn"], 159 | "test": ["pytest", "pytest-cov", "coverage", "flake8"], 160 | "lint": [ 161 | "pysen", 162 | "types-setuptools", 163 | "mypy<=0.910", 164 | "black>=19.19b0,<=20.8", 165 | "click<8.1.0", 166 | "flake8>=3.7,<4", 167 | "flake8-bugbear", 168 | "isort>=4.3,<5.2.0", 169 | "types-decorator", 170 | "importlib-metadata<5.0", 171 | ], 172 | }, 173 | classifiers=[ 174 | "Operating System :: Microsoft :: Windows", 175 | "Operating System :: POSIX", 176 | "Operating System :: Unix", 177 | "Operating System :: MacOS", 178 | "Programming Language :: Cython", 179 | "Programming Language :: Python", 180 | "Programming Language :: Python :: 3", 181 | "Programming Language :: Python :: 3.8", 182 | "Programming Language :: Python :: 3.9", 183 | "Programming Language :: Python :: 3.10", 184 | "Programming Language :: Python :: 3.11", 185 | "License :: OSI Approved :: MIT License", 186 | "Topic :: Scientific/Engineering", 187 | "Topic :: Software Development", 188 | "Intended Audience :: Science/Research", 189 | "Intended Audience :: Developers", 190 | ], 191 | keywords=["SPTK"], 192 | ) 193 | -------------------------------------------------------------------------------- /tests/data/arctic_a007_p16_L60_H240_o0_rapt.txt: -------------------------------------------------------------------------------- 1 | 0 2 | 0 3 | 0 4 | 0 5 | 0 6 | 0 7 | 0 8 | 0 9 | 0 10 | 0 11 | 0 12 | 0 13 | 0 14 | 0 15 | 0 16 | 0 17 | 0 18 | 0 19 | 0 20 | 0 21 | 0 22 | 0 23 | 0 24 | 0 25 | 0 26 | 0 27 | 0 28 | 0 29 | 0 30 | 0 31 | 0 32 | 0 33 | 0 34 | 0 35 | 0 36 | 0 37 | 0 38 | 0 39 | 0 40 | 0 41 | 0 42 | 0 43 | 0 44 | 0 45 | 0 46 | 0 47 | 0 48 | 0 49 | 0 50 | 0 51 | 0 52 | 0 53 | 0 54 | 0 55 | 0 56 | 0 57 | 0 58 | 0 59 | 0 60 | 0 61 | 0 62 | 0 63 | 0 64 | 0 65 | 0 66 | 0 67 | 0 68 | 0 69 | 0 70 | 0 71 | 0 72 | 0 73 | 0 74 | 0 75 | 0 76 | 0 77 | 0 78 | 0 79 | 0 80 | 0 81 | 0 82 | 0 83 | 0 84 | 0 85 | 0 86 | 125.508 87 | 125.32 88 | 124.158 89 | 122.423 90 | 121.442 91 | 120.566 92 | 120.622 93 | 121.352 94 | 120.511 95 | 120.391 96 | 120.064 97 | 131.003 98 | 128.177 99 | 118.787 100 | 119.792 101 | 120.679 102 | 122.355 103 | 123.83 104 | 123.74 105 | 126.936 106 | 129.479 107 | 129.393 108 | 131.918 109 | 132.26 110 | 138.124 111 | 138.685 112 | 143.383 113 | 0 114 | 0 115 | 0 116 | 0 117 | 137.755 118 | 132.787 119 | 132.264 120 | 126.935 121 | 128.205 122 | 125.85 123 | 125.281 124 | 125.033 125 | 125.017 126 | 125.189 127 | 124.909 128 | 124.439 129 | 124.104 130 | 123.793 131 | 123.462 132 | 123.523 133 | 122.031 134 | 120.938 135 | 120.492 136 | 119.321 137 | 116.135 138 | 114.765 139 | 112.328 140 | 107.556 141 | 104.546 142 | 103.594 143 | 90.3971 144 | 88.2725 145 | 88.919 146 | 83.7755 147 | 79.5028 148 | 75.5464 149 | 72.1872 150 | 0 151 | 0 152 | 0 153 | 0 154 | 0 155 | 0 156 | 216.45 157 | 216.05 158 | 217.023 159 | 242.43 160 | 120.288 161 | 118.753 162 | 120.216 163 | 120.507 164 | 120.69 165 | 119.013 166 | 116.565 167 | 115.279 168 | 114.65 169 | 112.035 170 | 111.235 171 | 110.316 172 | 110.723 173 | 110.181 174 | 109.562 175 | 108.71 176 | 107.904 177 | 107.45 178 | 107.163 179 | 106.243 180 | 105.825 181 | 105.44 182 | 105.325 183 | 105.956 184 | 106.152 185 | 106.033 186 | 106.106 187 | 105.965 188 | 105.665 189 | 105.607 190 | 105.726 191 | 107.907 192 | 109.121 193 | 109.825 194 | 109.086 195 | 109.291 196 | 108.557 197 | 108.331 198 | 108.139 199 | 107.744 200 | 108.22 201 | 109.577 202 | 109.152 203 | 109.831 204 | 111.849 205 | 112.814 206 | 114.683 207 | 117.075 208 | 118.378 209 | 121.709 210 | 125.186 211 | 126.823 212 | 134.808 213 | 0 214 | 0 215 | 0 216 | 0 217 | 0 218 | 0 219 | 0 220 | 0 221 | 0 222 | 0 223 | 0 224 | 0 225 | 0 226 | 0 227 | 0 228 | 0 229 | 0 230 | 0 231 | 0 232 | 0 233 | 0 234 | 0 235 | 0 236 | 0 237 | 0 238 | 111.061 239 | 111.765 240 | 113.811 241 | 116.797 242 | 117.474 243 | 117.413 244 | 116.454 245 | 116.658 246 | 118.059 247 | 119.461 248 | 121.078 249 | 120.709 250 | 120.652 251 | 122.107 252 | 128.479 253 | 131.173 254 | 121.08 255 | 118.022 256 | 116.163 257 | 116.973 258 | 117.709 259 | 121.199 260 | 120.694 261 | 120.527 262 | 134.1 263 | 0 264 | 0 265 | 0 266 | 0 267 | 0 268 | 0 269 | 0 270 | 0 271 | 0 272 | 0 273 | 0 274 | 0 275 | 0 276 | 0 277 | 0 278 | 0 279 | 0 280 | 0 281 | 0 282 | 0 283 | 0 284 | 127.527 285 | 131.284 286 | 132.174 287 | 137.47 288 | 139.087 289 | 0 290 | 0 291 | 0 292 | 0 293 | 0 294 | 0 295 | 0 296 | 0 297 | 0 298 | 0 299 | 0 300 | 0 301 | 0 302 | 0 303 | 0 304 | 0 305 | 0 306 | 0 307 | 0 308 | 0 309 | 0 310 | 0 311 | 0 312 | 0 313 | 0 314 | 0 315 | 0 316 | 0 317 | 0 318 | 0 319 | 0 320 | 94.2986 321 | 98.9601 322 | 100.839 323 | 106.27 324 | 105.707 325 | 105.923 326 | 106.087 327 | 106.781 328 | 107.48 329 | 109.282 330 | 109.5 331 | 112.074 332 | 114.463 333 | 114.964 334 | 118.759 335 | 121.503 336 | 122.36 337 | 126.577 338 | 130.973 339 | 131.61 340 | 132.494 341 | 134.206 342 | 134.831 343 | 137.805 344 | 137.701 345 | 139.424 346 | 139.692 347 | 146.586 348 | 145.872 349 | 146.668 350 | 147.762 351 | 148.093 352 | 149.266 353 | 149.623 354 | 149.676 355 | 149.889 356 | 150.569 357 | 152.389 358 | 155.768 359 | 157.761 360 | 0 361 | 0 362 | 0 363 | 0 364 | 0 365 | 0 366 | 0 367 | 0 368 | 0 369 | 0 370 | 0 371 | 0 372 | 0 373 | 0 374 | 0 375 | 0 376 | 0 377 | 0 378 | 0 379 | 0 380 | 0 381 | 0 382 | 0 383 | 0 384 | 0 385 | 0 386 | 0 387 | 0 388 | 0 389 | 0 390 | 0 391 | 0 392 | 0 393 | 0 394 | 139.514 395 | 133.439 396 | 133.952 397 | 134.593 398 | 136.023 399 | 136.048 400 | 136.752 401 | 136.274 402 | 139.333 403 | 134.75 404 | 133.224 405 | 129.485 406 | 128.698 407 | 128.291 408 | 129.839 409 | 130.348 410 | 130.937 411 | 130.303 412 | 130.068 413 | 131.187 414 | 131.268 415 | 132.442 416 | 132.294 417 | 132.425 418 | 132.222 419 | 131.306 420 | 129.708 421 | 121.164 422 | 121.49 423 | 133.89 424 | 137.336 425 | 137.792 426 | 142.248 427 | 142.704 428 | 148.307 429 | 148.499 430 | 162.39 431 | 0 432 | 0 433 | 0 434 | 0 435 | 0 436 | 0 437 | 0 438 | 0 439 | 0 440 | 0 441 | 0 442 | 0 443 | 0 444 | 0 445 | 0 446 | 0 447 | 0 448 | 0 449 | 0 450 | 0 451 | 0 452 | 0 453 | 0 454 | 0 455 | 0 456 | 0 457 | 125.134 458 | 124.432 459 | 145.492 460 | 146.08 461 | 135.733 462 | 0 463 | 0 464 | 0 465 | 0 466 | 0 467 | 0 468 | 0 469 | 0 470 | 0 471 | 0 472 | 0 473 | 0 474 | 0 475 | 0 476 | 0 477 | 0 478 | 0 479 | 0 480 | 0 481 | 0 482 | 0 483 | 0 484 | 0 485 | 0 486 | 0 487 | 0 488 | 0 489 | 0 490 | 0 491 | 0 492 | 0 493 | 0 494 | 0 495 | 109.487 496 | 111.854 497 | 113.89 498 | 114.206 499 | 115.355 500 | 115.57 501 | 115.586 502 | 117.498 503 | 117.097 504 | 118.065 505 | 119.604 506 | 120.377 507 | 120.883 508 | 121.489 509 | 122.419 510 | 121.912 511 | 120.995 512 | 122.656 513 | 122.782 514 | 120.5 515 | 121.872 516 | 122.311 517 | 122.003 518 | 124.222 519 | 124.825 520 | 145.239 521 | 136.445 522 | 133.314 523 | 123.66 524 | 125.779 525 | 128.445 526 | 128.041 527 | 127.956 528 | 125.979 529 | 127.03 530 | 127.467 531 | 129.17 532 | 130.027 533 | 130.406 534 | 128.786 535 | 128.333 536 | 135.031 537 | 134.191 538 | 137.84 539 | 138.698 540 | 138.907 541 | 142.158 542 | 143.453 543 | 149.365 544 | 147.884 545 | 155.756 546 | 0 547 | 0 548 | 0 549 | 0 550 | 0 551 | 0 552 | 0 553 | 0 554 | 0 555 | 0 556 | 0 557 | 0 558 | 0 559 | 0 560 | 0 561 | 0 562 | 132.476 563 | 130.881 564 | 136.382 565 | 137.215 566 | 141.255 567 | 142.041 568 | 147.823 569 | 148.802 570 | 150.573 571 | 152.762 572 | 153.791 573 | 158.068 574 | 157.644 575 | 160.581 576 | 162.504 577 | 164.094 578 | 163.512 579 | 0 580 | 0 581 | 0 582 | 0 583 | 0 584 | 0 585 | 0 586 | 0 587 | 0 588 | 0 589 | 0 590 | 0 591 | 0 592 | 0 593 | 0 594 | 0 595 | 0 596 | 0 597 | 0 598 | 0 599 | 0 600 | 0 601 | 0 602 | 0 603 | 0 604 | 0 605 | 0 606 | 0 607 | 133.486 608 | 133.545 609 | 138.573 610 | 140.148 611 | 142.014 612 | 145.819 613 | 147.986 614 | 0 615 | 0 616 | 0 617 | 0 618 | 0 619 | 0 620 | 0 621 | 0 622 | 0 623 | 0 624 | 0 625 | 0 626 | 0 627 | 0 628 | 0 629 | 0 630 | 0 631 | 0 632 | 0 633 | 0 634 | 129.48 635 | 130.898 636 | 142.671 637 | 143.709 638 | 143.876 639 | 144.671 640 | 144.264 641 | 138.311 642 | 138.296 643 | 137.639 644 | 136.853 645 | 136.459 646 | 136.481 647 | 136.76 648 | 137.967 649 | 138.299 650 | 139.25 651 | 141.117 652 | 141.876 653 | 144.175 654 | 144.647 655 | 146.513 656 | 147.488 657 | 149.608 658 | 150.505 659 | 152.66 660 | 155.95 661 | 156.913 662 | 161.272 663 | 161.38 664 | 163.096 665 | 168.633 666 | 169.41 667 | 172.405 668 | 174.187 669 | 175.314 670 | 177.395 671 | 176.123 672 | 175.436 673 | 179.272 674 | 179.788 675 | 181.498 676 | 183.411 677 | 188.605 678 | 189.037 679 | 188.513 680 | 195.212 681 | 194.939 682 | 201.107 683 | 190.961 684 | 187.189 685 | 0 686 | 0 687 | 0 688 | 0 689 | 0 690 | 0 691 | 0 692 | 0 693 | 0 694 | 0 695 | 0 696 | 0 697 | 0 698 | 0 699 | 0 700 | 0 701 | 0 702 | 0 703 | 0 704 | 0 705 | 0 706 | 0 707 | 0 708 | 0 709 | 0 710 | 0 711 | 0 712 | 0 713 | 0 714 | 0 715 | 0 716 | 0 717 | 0 718 | 0 719 | 0 720 | 0 721 | 0 722 | 0 723 | 0 724 | 0 725 | 0 726 | 0 727 | 0 728 | 0 729 | 0 730 | 0 731 | 0 732 | 0 733 | 0 734 | 0 735 | 0 736 | 0 737 | 0 738 | 0 739 | 0 740 | 0 741 | 0 742 | 0 743 | 0 744 | 0 745 | 0 746 | 0 747 | 0 748 | 0 749 | 0 750 | 0 751 | 0 752 | 0 753 | 0 754 | 0 755 | 0 756 | 0 757 | 0 758 | 0 759 | 0 760 | 0 761 | 0 762 | 0 763 | 0 764 | 0 765 | 0 766 | 0 767 | 0 768 | 0 769 | 0 770 | 0 771 | 0 772 | 0 773 | 0 774 | 0 775 | 0 776 | 0 777 | 0 778 | 0 779 | 0 780 | 0 781 | 0 782 | 0 783 | 0 784 | 0 785 | 0 786 | 0 787 | 0 788 | 0 789 | 0 790 | 0 791 | 0 792 | 0 793 | 0 794 | 0 795 | 0 796 | 0 797 | 0 798 | 0 799 | 0 800 | 0 801 | -------------------------------------------------------------------------------- /tests/data/arctic_a007_p16_L60_H240_o0_swipe.txt: -------------------------------------------------------------------------------- 1 | 0 2 | 0 3 | 0 4 | 0 5 | 0 6 | 0 7 | 0 8 | 0 9 | 0 10 | 0 11 | 0 12 | 0 13 | 0 14 | 0 15 | 0 16 | 0 17 | 0 18 | 0 19 | 0 20 | 0 21 | 0 22 | 0 23 | 0 24 | 0 25 | 0 26 | 0 27 | 0 28 | 0 29 | 0 30 | 0 31 | 0 32 | 0 33 | 0 34 | 0 35 | 0 36 | 0 37 | 0 38 | 0 39 | 0 40 | 0 41 | 0 42 | 0 43 | 0 44 | 0 45 | 0 46 | 0 47 | 0 48 | 0 49 | 0 50 | 0 51 | 0 52 | 0 53 | 0 54 | 0 55 | 0 56 | 0 57 | 0 58 | 0 59 | 0 60 | 0 61 | 0 62 | 0 63 | 0 64 | 0 65 | 0 66 | 0 67 | 0 68 | 0 69 | 0 70 | 0 71 | 0 72 | 0 73 | 0 74 | 0 75 | 0 76 | 0 77 | 0 78 | 0 79 | 0 80 | 0 81 | 0 82 | 0 83 | 0 84 | 0 85 | 0 86 | 0 87 | 0 88 | 123.041 89 | 123.152 90 | 123.152 91 | 123.152 92 | 123.041 93 | 122.93 94 | 122.709 95 | 122.266 96 | 121.716 97 | 121.387 98 | 121.496 99 | 121.606 100 | 121.716 101 | 121.826 102 | 121.826 103 | 121.936 104 | 122.487 105 | 123.375 106 | 124.944 107 | 126.191 108 | 127.795 109 | 128.605 110 | 129.888 111 | 130.358 112 | 130.711 113 | 131.184 114 | 131.659 115 | 0 116 | 0 117 | 0 118 | 0 119 | 128.142 120 | 127.334 121 | 126.304 122 | 125.963 123 | 125.736 124 | 125.622 125 | 125.395 126 | 125.283 127 | 125.283 128 | 125.17 129 | 125.17 130 | 124.831 131 | 124.381 132 | 123.598 133 | 123.041 134 | 122.377 135 | 121.496 136 | 120.622 137 | 119.646 138 | 118.038 139 | 116.451 140 | 114.781 141 | 111.212 142 | 0 143 | 0 144 | 0 145 | 0 146 | 0 147 | 0 148 | 0 149 | 0 150 | 0 151 | 0 152 | 0 153 | 0 154 | 0 155 | 0 156 | 0 157 | 0 158 | 0 159 | 0 160 | 0 161 | 121.606 162 | 120.514 163 | 119.863 164 | 119.431 165 | 118.357 166 | 118.038 167 | 117.612 168 | 116.345 169 | 115.508 170 | 114.367 171 | 112.829 172 | 111.111 173 | 110.511 174 | 110.113 175 | 109.716 176 | 109.124 177 | 108.632 178 | 108.046 179 | 107.268 180 | 106.689 181 | 106.593 182 | 106.497 183 | 106.304 184 | 106.113 185 | 106.017 186 | 105.826 187 | 105.73 188 | 105.73 189 | 105.826 190 | 106.017 191 | 106.209 192 | 106.497 193 | 106.593 194 | 106.882 195 | 107.172 196 | 107.851 197 | 108.241 198 | 108.632 199 | 108.927 200 | 109.617 201 | 110.711 202 | 111.312 203 | 112.22 204 | 112.829 205 | 113.238 206 | 113.852 207 | 115.3 208 | 116.345 209 | 117.931 210 | 120.187 211 | 122.487 212 | 123.486 213 | 124.494 214 | 125.057 215 | 0 216 | 0 217 | 0 218 | 0 219 | 0 220 | 0 221 | 0 222 | 0 223 | 0 224 | 0 225 | 0 226 | 0 227 | 0 228 | 0 229 | 0 230 | 0 231 | 0 232 | 0 233 | 0 234 | 0 235 | 0 236 | 0 237 | 0 238 | 0 239 | 115.196 240 | 115.717 241 | 116.031 242 | 116.345 243 | 116.661 244 | 116.977 245 | 117.506 246 | 117.825 247 | 118.144 248 | 119.323 249 | 120.079 250 | 120.731 251 | 121.058 252 | 120.949 253 | 120.95 254 | 120.84 255 | 120.405 256 | 119.971 257 | 118.144 258 | 118.251 259 | 119.323 260 | 119.431 261 | 119.538 262 | 119.646 263 | 119.755 264 | 0 265 | 0 266 | 0 267 | 0 268 | 0 269 | 0 270 | 0 271 | 0 272 | 0 273 | 0 274 | 0 275 | 0 276 | 0 277 | 0 278 | 0 279 | 0 280 | 0 281 | 0 282 | 0 283 | 0 284 | 0 285 | 0 286 | 0 287 | 0 288 | 135.639 289 | 135.761 290 | 135.883 291 | 0 292 | 0 293 | 0 294 | 0 295 | 0 296 | 0 297 | 0 298 | 0 299 | 0 300 | 0 301 | 0 302 | 0 303 | 0 304 | 0 305 | 0 306 | 0 307 | 0 308 | 0 309 | 0 310 | 0 311 | 0 312 | 0 313 | 0 314 | 0 315 | 0 316 | 0 317 | 0 318 | 0 319 | 0 320 | 0 321 | 0 322 | 0 323 | 0 324 | 106.113 325 | 106.304 326 | 106.401 327 | 106.401 328 | 106.689 329 | 107.365 330 | 109.222 331 | 111.513 332 | 113.238 333 | 114.574 334 | 115.822 335 | 118.038 336 | 120.187 337 | 123.375 338 | 127.105 339 | 128.489 340 | 130.711 341 | 131.302 342 | 132.613 343 | 134.906 344 | 136.375 345 | 138.609 346 | 139.74 347 | 140.498 348 | 142.028 349 | 143.704 350 | 144.876 351 | 146.983 352 | 147.915 353 | 148.584 354 | 148.718 355 | 148.987 356 | 149.121 357 | 149.391 358 | 149.661 359 | 149.931 360 | 0 361 | 0 362 | 0 363 | 0 364 | 0 365 | 0 366 | 0 367 | 0 368 | 0 369 | 0 370 | 0 371 | 0 372 | 0 373 | 0 374 | 0 375 | 0 376 | 0 377 | 0 378 | 0 379 | 0 380 | 0 381 | 0 382 | 0 383 | 0 384 | 0 385 | 0 386 | 0 387 | 0 388 | 0 389 | 0 390 | 0 391 | 0 392 | 0 393 | 0 394 | 0 395 | 0 396 | 133.212 397 | 133.212 398 | 133.212 399 | 133.212 400 | 133.212 401 | 133.212 402 | 133.333 403 | 133.333 404 | 133.453 405 | 132.613 406 | 131.302 407 | 130.593 408 | 130.24 409 | 129.888 410 | 129.537 411 | 129.42 412 | 129.771 413 | 130.005 414 | 130.24 415 | 130.475 416 | 130.711 417 | 130.947 418 | 131.065 419 | 131.065 420 | 131.065 421 | 131.184 422 | 131.302 423 | 131.421 424 | 132.972 425 | 135.028 426 | 136.006 427 | 138.109 428 | 140.752 429 | 143.316 430 | 144.746 431 | 0 432 | 0 433 | 0 434 | 0 435 | 0 436 | 0 437 | 0 438 | 0 439 | 0 440 | 0 441 | 0 442 | 0 443 | 0 444 | 0 445 | 0 446 | 0 447 | 0 448 | 0 449 | 0 450 | 0 451 | 0 452 | 0 453 | 0 454 | 0 455 | 0 456 | 0 457 | 0 458 | 0 459 | 0 460 | 0 461 | 0 462 | 0 463 | 0 464 | 0 465 | 0 466 | 0 467 | 0 468 | 0 469 | 0 470 | 0 471 | 0 472 | 0 473 | 0 474 | 0 475 | 0 476 | 0 477 | 0 478 | 0 479 | 0 480 | 0 481 | 0 482 | 0 483 | 0 484 | 0 485 | 0 486 | 0 487 | 0 488 | 0 489 | 0 490 | 0 491 | 0 492 | 0 493 | 0 494 | 0 495 | 0 496 | 0 497 | 114.264 498 | 114.781 499 | 115.092 500 | 115.3 501 | 115.613 502 | 116.135 503 | 116.871 504 | 117.825 505 | 118.464 506 | 119.323 507 | 119.646 508 | 119.971 509 | 120.405 510 | 120.95 511 | 121.277 512 | 121.496 513 | 121.826 514 | 121.826 515 | 121.936 516 | 122.046 517 | 122.266 518 | 122.487 519 | 122.708 520 | 123.152 521 | 124.045 522 | 125.17 523 | 126.304 524 | 127.219 525 | 127.564 526 | 127.91 527 | 127.91 528 | 127.91 529 | 128.026 530 | 128.026 531 | 128.142 532 | 128.141 533 | 128.489 534 | 128.837 535 | 130.005 536 | 131.302 537 | 133.092 538 | 134.056 539 | 135.15 540 | 135.516 541 | 136.252 542 | 137.488 543 | 139.361 544 | 0 545 | 0 546 | 0 547 | 0 548 | 0 549 | 0 550 | 0 551 | 0 552 | 0 553 | 0 554 | 0 555 | 0 556 | 0 557 | 0 558 | 0 559 | 0 560 | 0 561 | 0 562 | 0 563 | 0 564 | 131.659 565 | 132.732 566 | 0 567 | 139.865 568 | 142.028 569 | 145.138 570 | 146.19 571 | 147.249 572 | 147.915 573 | 149.931 574 | 151.564 575 | 153.768 576 | 154.604 577 | 156.287 578 | 156.428 579 | 156.569 580 | 156.711 581 | 156.993 582 | 0 583 | 0 584 | 0 585 | 0 586 | 0 587 | 0 588 | 0 589 | 0 590 | 0 591 | 0 592 | 0 593 | 0 594 | 0 595 | 0 596 | 0 597 | 0 598 | 0 599 | 0 600 | 0 601 | 0 602 | 0 603 | 0 604 | 0 605 | 0 606 | 0 607 | 0 608 | 0 609 | 0 610 | 0 611 | 0 612 | 0 613 | 0 614 | 143.445 615 | 144.485 616 | 145.007 617 | 0 618 | 0 619 | 0 620 | 0 621 | 0 622 | 0 623 | 0 624 | 0 625 | 0 626 | 0 627 | 0 628 | 0 629 | 0 630 | 0 631 | 0 632 | 0 633 | 0 634 | 0 635 | 0 636 | 0 637 | 0 638 | 137.985 639 | 139.236 640 | 139.739 641 | 140.118 642 | 139.361 643 | 138.609 644 | 137.985 645 | 137.612 646 | 137.239 647 | 136.992 648 | 137.239 649 | 137.86 650 | 138.484 651 | 139.613 652 | 140.879 653 | 141.9 654 | 142.671 655 | 143.575 656 | 144.876 657 | 147.249 658 | 148.584 659 | 150.337 660 | 151.154 661 | 152.25 662 | 155.723 663 | 157.562 664 | 160.866 665 | 162.765 666 | 165.431 667 | 166.479 668 | 167.534 669 | 168.748 670 | 169.512 671 | 172.599 672 | 173.38 673 | 175.11 674 | 175.902 675 | 177.177 676 | 179.591 677 | 182.697 678 | 184.354 679 | 185.522 680 | 186.193 681 | 186.53 682 | 0 683 | 0 684 | 0 685 | 0 686 | 0 687 | 0 688 | 0 689 | 0 690 | 0 691 | 0 692 | 0 693 | 0 694 | 0 695 | 0 696 | 0 697 | 0 698 | 0 699 | 0 700 | 0 701 | 0 702 | 0 703 | 0 704 | 0 705 | 0 706 | 0 707 | 0 708 | 0 709 | 0 710 | 0 711 | 0 712 | 0 713 | 0 714 | 0 715 | 0 716 | 0 717 | 0 718 | 0 719 | 0 720 | 0 721 | 0 722 | 0 723 | 0 724 | 0 725 | 0 726 | 0 727 | 0 728 | 0 729 | 0 730 | 0 731 | 0 732 | 0 733 | 0 734 | 0 735 | 0 736 | 0 737 | 0 738 | 0 739 | 0 740 | 0 741 | 0 742 | 0 743 | 0 744 | 0 745 | 0 746 | 0 747 | 0 748 | 0 749 | 0 750 | 0 751 | 0 752 | 0 753 | 0 754 | 0 755 | 0 756 | 0 757 | 0 758 | 0 759 | 0 760 | 0 761 | 0 762 | 0 763 | 0 764 | 0 765 | 0 766 | 0 767 | 0 768 | 0 769 | 0 770 | 0 771 | 0 772 | 0 773 | 0 774 | 0 775 | 0 776 | 0 777 | 0 778 | 0 779 | 0 780 | 0 781 | 0 782 | 0 783 | 0 784 | 0 785 | 0 786 | 0 787 | 0 788 | 0 789 | 0 790 | 0 791 | 0 792 | 0 793 | 0 794 | 0 795 | 0 796 | 0 797 | 0 798 | 0 799 | 0 800 | 0 801 | -------------------------------------------------------------------------------- /tests/data/test16k.cdist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r9y9/pysptk/65c26f5cac3caf8af031ef100c53369c3c83c5ef/tests/data/test16k.cdist -------------------------------------------------------------------------------- /tests/data/test16k.cep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r9y9/pysptk/65c26f5cac3caf8af031ef100c53369c3c83c5ef/tests/data/test16k.cep -------------------------------------------------------------------------------- /tests/data/test16k.float: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r9y9/pysptk/65c26f5cac3caf8af031ef100c53369c3c83c5ef/tests/data/test16k.float -------------------------------------------------------------------------------- /tests/data/test16k.lpc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r9y9/pysptk/65c26f5cac3caf8af031ef100c53369c3c83c5ef/tests/data/test16k.lpc -------------------------------------------------------------------------------- /tests/data/test16k.lsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r9y9/pysptk/65c26f5cac3caf8af031ef100c53369c3c83c5ef/tests/data/test16k.lsp -------------------------------------------------------------------------------- /tests/data/test16k.lsp2lpc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r9y9/pysptk/65c26f5cac3caf8af031ef100c53369c3c83c5ef/tests/data/test16k.lsp2lpc -------------------------------------------------------------------------------- /tests/data/test16k.mcep.cep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r9y9/pysptk/65c26f5cac3caf8af031ef100c53369c3c83c5ef/tests/data/test16k.mcep.cep -------------------------------------------------------------------------------- /tests/data/test16k_57.mgc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r9y9/pysptk/65c26f5cac3caf8af031ef100c53369c3c83c5ef/tests/data/test16k_57.mgc -------------------------------------------------------------------------------- /tests/data/test16k_57.sp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r9y9/pysptk/65c26f5cac3caf8af031ef100c53369c3c83c5ef/tests/data/test16k_57.sp -------------------------------------------------------------------------------- /tests/regression/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r9y9/pysptk/65c26f5cac3caf8af031ef100c53369c3c83c5ef/tests/regression/__init__.py -------------------------------------------------------------------------------- /tests/regression/test_metrics.py: -------------------------------------------------------------------------------- 1 | from os.path import dirname, join 2 | 3 | import numpy as np 4 | import pysptk 5 | import pytest 6 | 7 | DATA_DIR = join(dirname(__file__), "..", "data") 8 | 9 | 10 | def test_cdist_invalid(): 11 | c1 = np.random.rand(10, 26) 12 | c2 = np.random.rand(10, 26) 13 | 14 | def __test_invalid(otype): 15 | pysptk.cdist(c1, c2, otype=otype) 16 | 17 | with pytest.raises(ValueError): 18 | __test_invalid(-1) 19 | with pytest.raises(ValueError): 20 | __test_invalid(3) 21 | 22 | 23 | def test_cdist(): 24 | order = 24 25 | # frame -l 512 -p 80 < test16k.float | window -l 512 \ 26 | # | mcep -q 0 -l 512 -a 0.41 -m 24 | freqt -a 0.41 -m 24 -A 0 -M 24 > test16k.mcep.cep 27 | c1 = np.fromfile(join(DATA_DIR, "test16k.mcep.cep"), dtype=np.float32).reshape( 28 | -1, order + 1 29 | ) 30 | # frame -l 512 -p 80 < test16k.float | window -l 512 | fftcep -m 24 -l 512 > test16k.cep 31 | c2 = np.fromfile(join(DATA_DIR, "test16k.cep"), dtype=np.float32).reshape( 32 | -1, order + 1 33 | ) 34 | 35 | assert c1.shape == c2.shape 36 | # cdist test16k.cep -m 24 -o 0 < test16k.mcep.cep | dmp +f 37 | assert np.allclose(pysptk.cdist(c1, c2), 1.89798) 38 | assert np.allclose(pysptk.cdist(c1, c2, otype=0), 1.89798) 39 | # cdist test16k.cep -m 24 -o 1 < test16k.mcep.cep | dmp +f 40 | assert np.allclose(pysptk.cdist(c1, c2, otype=1), 0.10249) 41 | # cdist test16k.cep -m 24 -o 2 < test16k.mcep.cep | dmp +f 42 | assert np.allclose(pysptk.cdist(c1, c2, otype=2), 0.309023) 43 | 44 | # cdist test16k.cep -m 24 -o 0 -f < test16k.mcep.cep > test16k.cdist 45 | d = np.fromfile(join(DATA_DIR, "test16k.cdist"), dtype=np.float32) 46 | d_hat = pysptk.cdist(c1, c2, otype=0, frame=True) 47 | assert np.allclose(d, d_hat) 48 | -------------------------------------------------------------------------------- /tests/regression/test_mgcep.py: -------------------------------------------------------------------------------- 1 | from os.path import dirname, join 2 | 3 | import numpy as np 4 | import pysptk 5 | 6 | DATA_DIR = join(dirname(__file__), "..", "data") 7 | 8 | 9 | def test_lpc(): 10 | # frame -l 512 -p 80 < test16k.float | window -l 512 | dmp +f | awk \ 11 | # '{print $2}' > test16k_windowed.txt 12 | frames = ( 13 | np.loadtxt(join(DATA_DIR, "test16k_windowed.txt")) 14 | .reshape(759, 512) 15 | .astype(np.float64) 16 | ) 17 | # frame -l 512 -p 80 < test16k.float | window -l 512 | lpc -m 25 -l 512 > test16k.lpc 18 | lpc = ( 19 | np.fromfile(join(DATA_DIR, "test16k.lpc"), np.float32) 20 | .reshape(759, 26) 21 | .astype(np.float64) 22 | ) 23 | lpc_hat = pysptk.lpc(frames, order=25) 24 | # yeah may have a bug... 25 | assert np.allclose(lpc, lpc_hat, atol=1e-1) 26 | 27 | 28 | def test_lpc2lsp(): 29 | # https://sourceforge.net/p/sp-tk/bugs/95/ 30 | # TODO: regenerate test data 31 | assert True 32 | 33 | # frame -l 512 -p 80 < test16k.float | window -l 512 | lpc -m 25 -l 512 > test16k.lpc 34 | # lpc = ( 35 | # np.fromfile(join(DATA_DIR, "test16k.lpc"), np.float32) 36 | # .reshape(759, 26) 37 | # .astype(np.float64) 38 | # ) 39 | # # frame -l 512 -p 80 < test16k.float | window -l 512 | lpc -m 25 -l 512 | 40 | # # lpc2lsp -m 25 > test16k.lsp 41 | # lsp = ( 42 | # np.fromfile(join(DATA_DIR, "test16k.lsp"), np.float32) 43 | # .reshape(759, 26) 44 | # .astype(np.float64) 45 | # ) 46 | # lsp_hat = pysptk.lpc2lsp(lpc) 47 | # assert np.allclose(lsp, lsp_hat, atol=1e-4) 48 | 49 | 50 | def test_lsp2lpc(): 51 | # frame -l 512 -p 80 < test16k.float | window -l 512 | lpc -m 25 -l 512 \ 52 | # | lpc2lsp -m 25 | lsp2lpc -m 25 > test16k.lsp2lpc 53 | lpc = ( 54 | np.fromfile(join(DATA_DIR, "test16k.lsp2lpc"), np.float32) 55 | .reshape(759, 26) 56 | .astype(np.float64) 57 | ) 58 | # frame -l 512 -p 80 < test16k.float | window -l 512 | lpc -m 25 -l 512 | 59 | # lpc2lsp -m 25 > test16k.lsp 60 | lsp = ( 61 | np.fromfile(join(DATA_DIR, "test16k.lsp"), np.float32) 62 | .reshape(759, 26) 63 | .astype(np.float64) 64 | ) 65 | lpc_hat = pysptk.lsp2lpc(lsp) 66 | assert np.allclose(lpc, lpc_hat, atol=1e-4) 67 | 68 | 69 | def test_mcep_from_windowed_frames(): 70 | # frame -l 512 -p 80 < test16k.float | window -l 512 | mcep -q 0 -l 512 -a \ 71 | # 0.41 -m 24 | dmp +f | awk '{print $2}' > test16k_mcep.txt 72 | mc = ( 73 | np.loadtxt(join(DATA_DIR, "test16k_mcep.txt")) 74 | .reshape(759, 25) 75 | .astype(np.float64) 76 | ) 77 | 78 | # frame -l 512 -p 80 < test16k.float | window -l 512 | dmp +f | awk \ 79 | # '{print $2}' > test16k_windowed.txt 80 | frames = ( 81 | np.loadtxt(join(DATA_DIR, "test16k_windowed.txt")) 82 | .reshape(759, 512) 83 | .astype(np.float64) 84 | ) 85 | mc_hat = np.apply_along_axis(pysptk.mcep, 1, frames, order=24, alpha=0.41) 86 | 87 | assert mc.shape == mc_hat.shape 88 | assert np.allclose(mc, mc_hat, atol=5e-4) # TODO: should be smaller? 89 | 90 | 91 | def test_mcep_from_H(): 92 | """Test mel-cepstrum computation from power spectrum (|H(w)|^2)""" 93 | #  frame -l 512 -p 80 < test16k.float | window -l 512 | mcep -q 0 -l 512 \ 94 | # -a 0.41 -m 24 | mgc2sp -m 24 -a 0.41 -g 0 -l 512 -o 3 | mcep -q 4 -l 512 \ 95 | # -a 0.41 -m 24 | dmp +f | awk '{print $2}' > test16k_mcep_from_H.txt 96 | mc = ( 97 | np.loadtxt(join(DATA_DIR, "test16k_mcep_from_H.txt")) 98 | .reshape(759, 25) 99 | .astype(np.float64) 100 | ) 101 | 102 | # frame -l 512 -p 80 < test16k.float | window -l 512 | mcep -q 0 -l 512 -a \ 103 | # 0.41 -m 24 | mgc2sp -m 24 -a 0.41 -g 0 -l 512 -o 3 | dmp +f | awk \ 104 | # '{print $2}' > test16k_H.txt 105 | H = np.loadtxt(join(DATA_DIR, "test16k_H.txt")).reshape(759, 257).astype(np.float64) 106 | mc_hat = np.apply_along_axis(pysptk.mcep, 1, H, order=24, alpha=0.41, itype=4) 107 | 108 | assert mc.shape == mc_hat.shape 109 | assert np.allclose(mc, mc_hat, atol=1e-6) 110 | 111 | 112 | def test_mgc2sp(): 113 | """mgc2sp 114 | 115 | ref: https://github.com/r9y9/pysptk/issues/57 116 | """ 117 | # frame -l 512 -p 80 < test16k.float | window -l 512| mcep -q 0 -l 512 \ 118 | # -a 0.41 -m 24 | mgc2sp -a 0.41 -m 24 -l 512 -o 3 > test16k_57.sp 119 | # output type 3 means we get power spectrum |H(w)|^2 120 | sp = ( 121 | np.fromfile(join(DATA_DIR, "test16k_57.sp"), dtype=np.float32) 122 | .reshape(759, 257) 123 | .astype(np.float64) 124 | ) 125 | 126 | # frame -l 512 -p 80 < test16k.float | window -l 512 \ 127 | # | mcep -q 0 -l 512 -a 0.41 -m 24 > test16k_57.mgc 128 | mgc = ( 129 | np.fromfile(join(DATA_DIR, "test16k_57.mgc"), dtype=np.float32) 130 | .reshape(759, 25) 131 | .astype(np.float64) 132 | ) 133 | 134 | # mgc2sp does conversion: c(k) -> log H(w) 135 | # so convert it to |H(w)|^2 to get power spectrum 136 | sp_hat = np.exp(pysptk.mgc2sp(mgc, 0.41, 0, 512).real * 2) 137 | 138 | assert np.allclose(sp, sp_hat) 139 | -------------------------------------------------------------------------------- /tests/test_adaptive.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pysptk 3 | import pytest 4 | 5 | 6 | def windowed_dummy_data(N): 7 | np.random.seed(98765) 8 | return pysptk.hanning(N) * np.random.randn(N) 9 | 10 | 11 | # TODO: likely to have bugs in SPTK 12 | @pytest.mark.parametrize("order", [20, 22, 25]) 13 | @pytest.mark.parametrize("pd", [4, 5]) 14 | def test_acep(order, pd): 15 | return 16 | # x = windowed_dummy_data(64) 17 | # c = np.zeros(order + 1) 18 | # for v in x: 19 | # pysptk.acep(v, c, pd=pd) 20 | # assert np.all(np.isfinite(c)) 21 | 22 | 23 | def test_acep_corner_case(): 24 | def __test(order, pd): 25 | x = windowed_dummy_data(64) 26 | c = np.zeros(order + 1) 27 | for v in x: 28 | pysptk.acep(v, c, pd=pd) 29 | 30 | # invalid pade 31 | with pytest.raises(ValueError): 32 | __test(20, 3) 33 | with pytest.raises(ValueError): 34 | __test(20, 8) 35 | 36 | 37 | @pytest.mark.parametrize("order", [20, 22, 25]) 38 | # TODO: likely to have bugs in SPTK 39 | # @pytest.mark.parametrize("stage", [1, 2, 3, 4, 5, 6, 7, 8, 9]) 40 | @pytest.mark.parametrize("stage", [1, 2]) 41 | def test_agcep(order, stage): 42 | x = windowed_dummy_data(64) 43 | c = np.zeros(order + 1) 44 | for v in x: 45 | pysptk.agcep(v, c, stage=stage) 46 | assert np.all(np.isfinite(c)) 47 | 48 | 49 | def test_agcep_corner_case(): 50 | def __test(order, stage): 51 | x = windowed_dummy_data(64) 52 | c = np.zeros(order + 1) 53 | for v in x: 54 | pysptk.agcep(v, c, stage=stage) 55 | 56 | # invalid stage 57 | with pytest.raises(ValueError): 58 | __test(20, 0) 59 | 60 | 61 | @pytest.mark.parametrize("order", [20, 22, 25]) 62 | @pytest.mark.parametrize("alpha", [0.0, 0.35, 0.5]) 63 | def test_amcep(order, alpha, pd=5): 64 | x = windowed_dummy_data(64) 65 | c = np.zeros(order + 1) 66 | for v in x: 67 | pysptk.amcep(v, c, alpha=alpha, pd=pd) 68 | assert np.all(np.isfinite(c)) 69 | 70 | 71 | def test_amcep_corner_case(): 72 | def __test(order, alpha, pd=5): 73 | x = windowed_dummy_data(64) 74 | c = np.zeros(order + 1) 75 | for v in x: 76 | pysptk.amcep(v, c, alpha=alpha, pd=pd) 77 | 78 | # invalid pade 79 | with pytest.raises(ValueError): 80 | __test(20, 0.35, 3) 81 | with pytest.raises(ValueError): 82 | __test(20, 0.35, 8) 83 | -------------------------------------------------------------------------------- /tests/test_conversions.py: -------------------------------------------------------------------------------- 1 | from warnings import warn 2 | 3 | import numpy as np 4 | import pysptk 5 | import pytest 6 | 7 | 8 | def windowed_dummy_data(N): 9 | np.random.seed(98765) 10 | return pysptk.hanning(N) * np.random.randn(N) 11 | 12 | 13 | def __test_conversion_base(f, src_order, dst_order, *args, **kwargs): 14 | np.random.seed(98765) 15 | src = np.random.rand(src_order + 1) 16 | dst = f(src, dst_order, *args, **kwargs) 17 | 18 | assert np.all(np.isfinite(dst)) 19 | 20 | 21 | def __test_transform_base(f, order, *args, **kwargs): 22 | np.random.seed(98765) 23 | src = np.random.rand(order + 1) 24 | dst = f(src, *args, **kwargs) 25 | 26 | assert np.all(np.isfinite(dst)) 27 | 28 | 29 | @pytest.mark.parametrize("src_order", [15, 20, 25, 30]) 30 | @pytest.mark.parametrize("dst_order", [15, 20, 25, 30]) 31 | def test_lpc2c(src_order, dst_order): 32 | __test_conversion_base(pysptk.lpc2c, src_order, dst_order) 33 | 34 | 35 | def test_lpc2lsp(): 36 | # for order in [15, 20, 25, 30]: 37 | # yield __test_transform_base, pysptk.lpc2lsp, order 38 | 39 | def __test_invalid_otype(dummy_lpc, otype): 40 | pysptk.lpc2lsp(dummy_lpc, otype=otype) 41 | 42 | np.random.seed(98765) 43 | dummy_lpc = pysptk.lpc(np.random.rand(512), 21) 44 | 45 | # invalid otype 46 | with pytest.raises(ValueError): 47 | __test_invalid_otype(dummy_lpc, 2) 48 | with pytest.raises(ValueError): 49 | __test_invalid_otype(dummy_lpc, 3) 50 | 51 | lsp1 = pysptk.lpc2lsp(dummy_lpc, otype=2, fs=16000) 52 | lsp2 = pysptk.lpc2lsp(dummy_lpc, otype=3, fs=16) 53 | assert np.allclose(lsp1, lsp2) 54 | 55 | # loggain 56 | lsp3 = pysptk.lpc2lsp(dummy_lpc, otype=3, fs=16, loggain=True) 57 | assert lsp3[0] == np.log(lsp2[0]) 58 | 59 | 60 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 61 | def test_lpc2par(order): 62 | __test_transform_base(pysptk.lpc2par, order) 63 | 64 | 65 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 66 | def test_par2lpc(order): 67 | __test_transform_base(pysptk.par2lpc, order) 68 | 69 | 70 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 71 | @pytest.mark.parametrize("fftlen", [256, 512, 1024]) 72 | def test_lsp2sp(order, fftlen): 73 | __test_transform_base(pysptk.lsp2sp, order, fftlen) 74 | 75 | 76 | def test_lsp2sp_fftlen(): 77 | def __test_fftlen(fftlen): 78 | pysptk.lsp2sp(np.ones(20), fftlen) 79 | 80 | with pytest.raises(ValueError): 81 | __test_fftlen(257) 82 | with pytest.raises(ValueError): 83 | __test_fftlen(513) 84 | 85 | 86 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 87 | @pytest.mark.parametrize("alpha", [0.35, 0.41, 0.5]) 88 | def test_mc2b(order, alpha): 89 | __test_transform_base(pysptk.mc2b, order, alpha) 90 | 91 | 92 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 93 | @pytest.mark.parametrize("alpha", [0.35, 0.41, 0.5]) 94 | def test_b2mc(order, alpha): 95 | __test_transform_base(pysptk.b2mc, order, alpha) 96 | 97 | 98 | @pytest.mark.parametrize("src_order", [15, 20, 25, 30]) 99 | @pytest.mark.parametrize("dst_order", [15, 20, 25, 30]) 100 | @pytest.mark.parametrize("alpha", [0.35, 0.41, 0.5]) 101 | def test_b2c(src_order, dst_order, alpha): 102 | __test_conversion_base(pysptk.b2c, src_order, dst_order, alpha) 103 | 104 | 105 | @pytest.mark.parametrize("src_order", [15, 20, 25, 30]) 106 | @pytest.mark.parametrize("dst_order", [15, 20, 25, 30]) 107 | @pytest.mark.parametrize("fftlen", [256, 512, 1024]) 108 | def test_c2acr(src_order, dst_order, fftlen): 109 | __test_transform_base(pysptk.b2c, src_order, dst_order, fftlen) 110 | 111 | 112 | def test_c2acr_fftlen(): 113 | def __test_fftlen(fftlen): 114 | pysptk.c2acr(np.ones(20), 19, fftlen) 115 | 116 | with pytest.raises(ValueError): 117 | __test_fftlen(257) 118 | with pytest.raises(ValueError): 119 | __test_fftlen(513) 120 | with pytest.raises(ValueError): 121 | __test_fftlen(16) 122 | 123 | 124 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 125 | @pytest.mark.parametrize("length", [256, 512, 1024]) 126 | def test_c2ir(order, length): 127 | __test_conversion_base(pysptk.c2ir, order, length) 128 | 129 | 130 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 131 | @pytest.mark.parametrize("length", [256, 512, 1024]) 132 | def test_ic2ir(order, length): 133 | __test_conversion_base(pysptk.ic2ir, length, order) 134 | 135 | 136 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 137 | @pytest.mark.parametrize("length", [256, 512, 1024]) 138 | def test_ic2ir_invertibility(order, length): 139 | np.random.seed(98765) 140 | dummy_ceps = np.random.rand(order + 1) 141 | ir = pysptk.c2ir(dummy_ceps, length) 142 | c = pysptk.ic2ir(ir, order) 143 | assert np.allclose(c, dummy_ceps) 144 | 145 | 146 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 147 | @pytest.mark.parametrize("fftlen", [256, 512, 1024]) 148 | def test_c2ndps(order, fftlen): 149 | __test_conversion_base(pysptk.c2ndps, order, fftlen) 150 | 151 | 152 | def test_c2ndps_fftlen(): 153 | # invalid fftlen 154 | with pytest.raises(ValueError): 155 | __test_conversion_base(pysptk.c2ndps, 20, 255) 156 | with pytest.raises(ValueError): 157 | __test_conversion_base(pysptk.c2ndps, 20, 257) 158 | 159 | 160 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 161 | @pytest.mark.parametrize("fftlen", [256, 512, 1024]) 162 | def test_ndps2c(order, fftlen): 163 | __test_conversion_base(pysptk.ndps2c, (fftlen >> 1), order) 164 | 165 | 166 | def test_ndps2c_fftlen(): 167 | def __test(length): 168 | pysptk.ndps2c(np.ones(length), 20) 169 | 170 | # invalid fftlen 171 | with pytest.raises(ValueError): 172 | __test(255 >> 1) 173 | with pytest.raises(ValueError): 174 | __test(257 >> 1) 175 | 176 | 177 | @pytest.mark.parametrize("src_order", [15, 20, 25, 30]) 178 | @pytest.mark.parametrize("src_gamma", [-1.0, -0.5, 0.0]) 179 | @pytest.mark.parametrize("dst_order", [15, 20, 25, 30]) 180 | @pytest.mark.parametrize("dst_gamma", [-1.0, -0.5, 0.0]) 181 | def test_gc2gc(src_order, src_gamma, dst_order, dst_gamma): 182 | np.random.seed(98765) 183 | src = np.random.rand(src_order + 1) 184 | dst = pysptk.gc2gc(src, src_gamma, dst_order, dst_gamma) 185 | assert np.all(np.isfinite(dst)) 186 | 187 | 188 | def test_gc2gc_gamma(): 189 | def __test(src_order, src_gamma, dst_order, dst_gamma): 190 | np.random.seed(98765) 191 | src = np.random.rand(src_order + 1) 192 | dst = pysptk.gc2gc(src, src_gamma, dst_order, dst_gamma) 193 | assert np.all(np.isfinite(dst)) 194 | 195 | # invalid gamma 196 | with pytest.raises(ValueError): 197 | __test(20, 0.0, 20, 0.1) 198 | with pytest.raises(ValueError): 199 | __test(20, 0.1, 20, 0.0) 200 | 201 | 202 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 203 | @pytest.mark.parametrize("gamma", [-1.0, -0.5, 0.0]) 204 | def test_gnorm(order, gamma): 205 | __test_transform_base(pysptk.gnorm, order, gamma) 206 | 207 | 208 | def test_gnorm_gamma(): 209 | # invalid gamma 210 | with pytest.raises(ValueError): 211 | __test_transform_base(pysptk.gnorm, 20, 0.1) 212 | 213 | 214 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 215 | @pytest.mark.parametrize("gamma", [-1.0, -0.5, 0.0]) 216 | def test_ignorm(order, gamma): 217 | __test_transform_base(pysptk.ignorm, order, gamma) 218 | 219 | 220 | def test_ignorm_gamma(): 221 | # invalid gamma 222 | with pytest.raises(ValueError): 223 | __test_transform_base(pysptk.ignorm, 20, 0.1) 224 | 225 | 226 | @pytest.mark.parametrize("src_order", [15, 20, 25, 30]) 227 | @pytest.mark.parametrize("dst_order", [15, 20, 25, 30]) 228 | @pytest.mark.parametrize("alpha", [0.35, 0.41, 0.5]) 229 | def test_freqt(src_order, dst_order, alpha): 230 | __test_conversion_base(pysptk.freqt, src_order, dst_order, alpha) 231 | 232 | 233 | @pytest.mark.parametrize("src_order", [15, 20, 25, 30]) 234 | @pytest.mark.parametrize("src_alpha", [0.35, 0.41, 0.5]) 235 | @pytest.mark.parametrize("src_gamma", [-1.0, -0.5, 0.0]) 236 | @pytest.mark.parametrize("dst_order", [15, 20, 25, 30]) 237 | @pytest.mark.parametrize("dst_alpha", [0.35, 0.41, 0.5]) 238 | @pytest.mark.parametrize("dst_gamma", [-1.0, -0.5, 0.0]) 239 | def test_mgc2mgc(src_order, src_alpha, src_gamma, dst_order, dst_alpha, dst_gamma): 240 | np.random.seed(98765) 241 | src = np.random.rand(src_order + 1) 242 | dst = pysptk.mgc2mgc(src, src_alpha, src_gamma, dst_order, dst_alpha, dst_gamma) 243 | assert np.all(np.isfinite(dst)) 244 | 245 | 246 | def test_mgc2mgc_gamma(): 247 | def __test(src_order, src_alpha, src_gamma, dst_order, dst_alpha, dst_gamma): 248 | np.random.seed(98765) 249 | src = np.random.rand(src_order + 1) 250 | dst = pysptk.mgc2mgc(src, src_alpha, src_gamma, dst_order, dst_alpha, dst_gamma) 251 | assert np.all(np.isfinite(dst)) 252 | 253 | # invalid gamma 254 | with pytest.raises(ValueError): 255 | __test(20, 0.0, 0.1, 20, 0.0, 0.0) 256 | with pytest.raises(ValueError): 257 | __test(20, 0.0, 0.0, 20, 0.0, 0.1) 258 | 259 | 260 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 261 | @pytest.mark.parametrize("alpha", [0.35, 0.41, 0.5]) 262 | @pytest.mark.parametrize("gamma", [-1.0, -0.5, 0.0]) 263 | @pytest.mark.parametrize("fftlen", [256, 512, 1024]) 264 | def test_mgc2sp(order, alpha, gamma, fftlen): 265 | np.random.seed(98765) 266 | src = np.random.rand(order + 1) 267 | dst = pysptk.mgc2sp(src, alpha, gamma, fftlen) 268 | assert len(dst) == (fftlen >> 1) + 1 269 | assert np.all(np.isfinite(dst)) 270 | 271 | 272 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 273 | @pytest.mark.parametrize("alpha", [0.35, 0.41, 0.5]) 274 | @pytest.mark.parametrize("gamma", [-1.0, -0.5, 0.0]) 275 | @pytest.mark.parametrize("fftlen", [256, 512, 1024]) 276 | def test_mgclsp2sp(order, alpha, gamma, fftlen): 277 | def __test(order, alpha, gamma, fftlen): 278 | np.random.seed(98765) 279 | src = np.random.rand(order + 1) 280 | dst = pysptk.mgclsp2sp(src, alpha, gamma, fftlen) 281 | assert len(dst) == (fftlen >> 1) + 1 282 | assert np.all(np.isfinite(dst)) 283 | 284 | # TODO 285 | if gamma == 0.0: 286 | warn("Inf/-Inf wiil happens when gamma = 0.0") 287 | return 288 | 289 | __test(order, alpha, gamma, fftlen) 290 | 291 | 292 | def test_mgclsp2sp_corner_case(): 293 | def __test(order, alpha, gamma, fftlen): 294 | np.random.seed(98765) 295 | src = np.random.rand(order + 1) 296 | pysptk.mgclsp2sp(src, alpha, gamma, fftlen) 297 | 298 | # invalid gamma 299 | with pytest.raises(ValueError): 300 | __test(20, 0.0, 0.1, 256) 301 | 302 | # invalid fftlen 303 | with pytest.raises(ValueError): 304 | __test(20, 0.0, -0.1, 255) 305 | with pytest.raises(ValueError): 306 | __test(20, 0.0, -0.1, 257) 307 | 308 | 309 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 310 | @pytest.mark.parametrize("alpha", [0.0, 0.35, 0.41]) 311 | @pytest.mark.parametrize("gamma", [-1.0, -0.5, 0.0]) 312 | def test_mgc2b(order, alpha, gamma): 313 | __test_transform_base(pysptk.mgc2b, order, alpha, gamma) 314 | 315 | 316 | @pytest.mark.parametrize("order", [10, 20, 40, 50, 60]) 317 | @pytest.mark.parametrize("alpha", [0.35, 0.41]) 318 | @pytest.mark.parametrize("fftlen", [512, 1024, 2048]) 319 | def test_sp2mc(order, alpha, fftlen): 320 | np.random.seed(98765) 321 | sp = np.random.rand(int(fftlen // 2 + 1)) 322 | mc = pysptk.sp2mc(sp, order, alpha) 323 | approx_sp = pysptk.mc2sp(mc, alpha, fftlen) 324 | # TODO: tolerance should be more carefully chosen 325 | assert np.allclose(sp, approx_sp, atol=0.9) 326 | 327 | 328 | def test_mc2e(): 329 | x = windowed_dummy_data(1024) 330 | mc = pysptk.mcep(x) 331 | assert pysptk.mc2e(mc) > 0 332 | -------------------------------------------------------------------------------- /tests/test_f0.py: -------------------------------------------------------------------------------- 1 | from os.path import dirname, join 2 | from warnings import warn 3 | 4 | import numpy as np 5 | import pysptk 6 | import pytest 7 | from scipy.io import wavfile 8 | 9 | 10 | @pytest.mark.parametrize("hopsize", [40, 80, 160, 320]) 11 | @pytest.mark.parametrize("otype", [0, 1, 2]) 12 | @pytest.mark.parametrize("otype_str", ["pitch", "f0", "logf0"]) 13 | def test_swipe(hopsize, otype, otype_str): 14 | def __test(x, fs, hopsize, otype): 15 | f0 = pysptk.swipe(x, fs, hopsize, otype=otype) 16 | assert np.all(np.isfinite(f0)) 17 | if otype == 1: 18 | assert np.all(f0 >= 0) 19 | 20 | np.random.seed(98765) 21 | fs = 16000 22 | x = np.random.rand(16000) 23 | 24 | __test(x, fs, hopsize, otype) 25 | __test(x, fs, 80, otype_str) 26 | 27 | 28 | def test_swipe_corner_case(): 29 | def __test(x, fs, hopsize, otype): 30 | pysptk.swipe(x, fs, hopsize, otype=otype) 31 | 32 | np.random.seed(98765) 33 | fs = 16000 34 | x = np.random.rand(16000) 35 | 36 | # unsupported otype 37 | with pytest.raises(ValueError): 38 | __test(x, fs, 80, -1) 39 | with pytest.raises(ValueError): 40 | __test(x, fs, 80, 3) 41 | with pytest.raises(ValueError): 42 | __test(x, fs, 80, "ff0") 43 | 44 | 45 | @pytest.mark.parametrize("hopsize", [40, 80, 160, 320]) 46 | @pytest.mark.parametrize("otype", [0, 1, 2]) 47 | @pytest.mark.parametrize("otype_str", ["pitch", "f0", "logf0"]) 48 | def test_rapt(hopsize, otype, otype_str): 49 | def __test(x, fs, hopsize, min, max, otype): 50 | f0 = pysptk.rapt(x, fs, hopsize, min=min, max=max, otype=otype) 51 | assert np.all(np.isfinite(f0)) 52 | if otype == 1: 53 | assert np.all(f0 >= 0) 54 | 55 | np.random.seed(98765) 56 | fs = 16000 57 | x = np.random.rand(16000).astype(np.float32) 58 | 59 | __test(x, fs, hopsize, 60, 240, otype) 60 | __test(x, fs, 80, 60, 240, otype_str) 61 | 62 | 63 | def test_rapt_corner_case(): 64 | def __test(x, fs, hopsize, min, max, otype): 65 | f0 = pysptk.rapt(x, fs, hopsize, min=min, max=max, otype=otype) 66 | assert np.all(np.isfinite(f0)) 67 | if otype == 1: 68 | assert np.all(f0 >= 0) 69 | 70 | np.random.seed(98765) 71 | fs = 16000 72 | x = np.random.rand(16000).astype(np.float32) 73 | 74 | # unsupported otype 75 | with pytest.raises(ValueError): 76 | __test(x, fs, 80, 60, 240, -1) 77 | with pytest.raises(ValueError): 78 | __test(x, fs, 80, 60, 240, 3) 79 | with pytest.raises(ValueError): 80 | __test(x, fs, 80, 60, 240, "f00") 81 | 82 | # valid min freq 83 | __test(x, fs, 80, 10, 240, 0) 84 | warn("TODO: fix RAPT bug to pass this minfreq lower bound test") 85 | # __test(x, fs, 80, fs / 10000. + 1, 240, 0) 86 | 87 | # valid max freq 88 | __test(x, fs, 80, 60, fs // 2 - 1, 0) 89 | 90 | # invalid min/max freq 91 | with pytest.raises(ValueError): 92 | __test(x, fs, 80, 60, 60, 0) 93 | with pytest.raises(ValueError): 94 | __test(x, fs, 80, 60, fs // 2, 0) 95 | with pytest.raises(ValueError): 96 | __test(x, fs, 80, fs / 10000.0, 240, 0) 97 | 98 | # valid frame_period (corner case) 99 | __test(x, fs, 1600, 60, 240, 0) 100 | __test(x, fs, 2, 60, 240, 0) 101 | 102 | warn("TODO: pass this corner case test") 103 | # __test(x, fs, 1, 60, 240, 0) 104 | 105 | # invalid frame_period 106 | with pytest.raises(ValueError): 107 | __test(x, fs, 1601, 60, 240, 0) 108 | 109 | # valid input length 110 | __test(x[:1000], fs, 80, 60, 240, 0) 111 | 112 | # invalid input length (too small) 113 | with pytest.raises(ValueError): 114 | __test(x[:100], fs, 80, 60, 240, 0) 115 | 116 | 117 | def test_rapt_regression(): 118 | # Grund truth data is generated by: 119 | # 120 | # $ wav2raw pysptk/example_audio_data/arctic_a0007.wav 121 | # 122 | # $ x2x +sf ./pysptk/example_audio_data/arctic_a0007.raw | \ 123 | # pitch -a 0 -s 16 -p 80 -L 60 -H 240 -o 0 > \ 124 | # arctic_a007_p16_L60_H240_o0_rapt.pitch 125 | # 126 | # $ dmp +f arctic_a007_p16_L60_H240_o0_rapt.pitch | awk '{print $2}' >\ 127 | # arctic_a007_p16_L60_H240_o0_rapt.txt 128 | # 129 | # $ pitch -h 130 | # ... 131 | # 132 | # SPTK: version 3.8 133 | # CVS Info: $Id: pitch.c,v 1.46 2014/12/11 08:30:43 uratec Exp $ 134 | 135 | ground_truth_path = join( 136 | dirname(__file__), "data", "arctic_a007_p16_L60_H240_o0_rapt.txt" 137 | ) 138 | with open(ground_truth_path) as f: 139 | ground_truth = np.asarray([float(s) for s in [line for line in f.readlines()]]) 140 | ground_truth = ground_truth.astype(np.float32) 141 | 142 | fs, x = wavfile.read(pysptk.util.example_audio_file()) 143 | assert fs == 16000 144 | 145 | # Since SPTK might have memory corruption bug and the result might be 146 | # non-deterministic, test it with multiple time... 147 | for _ in range(5): 148 | f0 = pysptk.rapt( 149 | x.astype(np.float32), 150 | fs=fs, 151 | hopsize=80, 152 | min=60, 153 | max=240, 154 | voice_bias=0.0, 155 | otype=0, 156 | ) 157 | assert np.allclose(ground_truth, f0) 158 | 159 | 160 | def test_swipe_regression(): 161 | # Grund truth data is generated by: 162 | # 163 | # $ wav2raw pysptk/example_audio_data/arctic_a0007.wav 164 | # 165 | # $ x2x +sf ./pysptk/example_audio_data/arctic_a0007.raw | \ 166 | # pitch -a 1 -s 16 -p 80 -L 60 -H 240 -o 0 > \ 167 | # arctic_a007_p16_L60_H240_o0_swipe.pitch 168 | # 169 | # $ dmp +f arctic_a007_p16_L60_H240_o0_swuoe.pitch | awk '{print $2}' >\ 170 | # arctic_a007_p16_L60_H240_o0_swipe.txt 171 | # 172 | # $ pitch -h 173 | # ... 174 | # 175 | # SPTK: version 3.10 176 | # CVS Info: $Id: pitch.c,v 1.53 2016/12/25 05:00:19 uratec Exp $ 177 | 178 | ground_truth_path = join( 179 | dirname(__file__), "data", "arctic_a007_p16_L60_H240_o0_swipe.txt" 180 | ) 181 | with open(ground_truth_path) as f: 182 | ground_truth = np.asarray([float(s) for s in [line for line in f.readlines()]]) 183 | ground_truth = ground_truth.astype(np.float32) 184 | 185 | fs, x = wavfile.read(pysptk.util.example_audio_file()) 186 | assert fs == 16000 187 | 188 | # Since SPTK might have memory corruption bug and the result might be 189 | # non-deterministic, test it with multiple time... 190 | for _ in range(5): 191 | f0 = pysptk.swipe( 192 | x.astype(np.float64), fs=fs, hopsize=80, min=60, max=240, otype=0 193 | ) 194 | assert np.allclose(ground_truth, f0) 195 | -------------------------------------------------------------------------------- /tests/test_lib.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pysptk 3 | 4 | 5 | def test_agexp(): 6 | assert pysptk.agexp(1, 1, 1) == 5.0 7 | assert pysptk.agexp(1, 2, 3) == 18.0 8 | 9 | 10 | def test_gexp(): 11 | assert pysptk.gexp(1, 1) == 2.0 12 | assert pysptk.gexp(2, 4) == 3.0 13 | 14 | 15 | def test_glog(): 16 | assert pysptk.glog(1, 2) == 1.0 17 | assert pysptk.glog(2, 3) == 4.0 18 | 19 | 20 | def test_mseq(): 21 | for _ in range(0, 100): 22 | assert np.isfinite(pysptk.mseq()) 23 | -------------------------------------------------------------------------------- /tests/test_mfcc.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pysptk 3 | import pytest 4 | 5 | 6 | def test_mfcc_options(): 7 | np.random.seed(98765) 8 | dummy_input = np.random.rand(512) 9 | 10 | # with c0 11 | cc = pysptk.mfcc(dummy_input, 12, czero=True) 12 | assert len(cc) == 13 13 | 14 | # wth c0 + power 15 | cc = pysptk.mfcc(dummy_input, 12, czero=True, power=True) 16 | assert len(cc) == 14 17 | 18 | # with power 19 | cc = pysptk.mfcc(dummy_input, 12, power=True) 20 | assert len(cc) == 13 21 | 22 | 23 | @pytest.mark.parametrize("n", [21, 23, 25]) 24 | def test_mfcc_num_filterbanks(n): 25 | def __test(n): 26 | np.random.seed(98765) 27 | dummy_input = np.random.rand(512) 28 | cc = pysptk.mfcc(dummy_input, 20, num_filterbanks=n) 29 | assert np.all(np.isfinite(cc)) 30 | 31 | __test(n) 32 | 33 | 34 | def test_mgcc_num_filterbanks_corner_case(): 35 | def __test(n): 36 | np.random.seed(98765) 37 | dummy_input = np.random.rand(512) 38 | pysptk.mfcc(dummy_input, 20, num_filterbanks=n) 39 | 40 | for n in [19, 20]: 41 | with pytest.raises(ValueError): 42 | __test(n) 43 | 44 | 45 | @pytest.mark.parametrize("order", [12, 14, 16, 18]) 46 | @pytest.mark.parametrize("length", [256, 512, 1024, 2048, 4096]) 47 | def test_mfcc(order, length): 48 | def __test(length, order): 49 | np.random.seed(98765) 50 | dummy_input = np.random.rand(length) 51 | cc = pysptk.mfcc(dummy_input, order, czero=True, power=True) 52 | assert np.all(np.isfinite(cc)) 53 | 54 | __test(length, order) 55 | -------------------------------------------------------------------------------- /tests/test_mgcep.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pysptk 3 | import pytest 4 | 5 | 6 | def windowed_dummy_data(N): 7 | np.random.seed(98765) 8 | return pysptk.hanning(N) * np.random.randn(N) 9 | 10 | 11 | def windowed_dummy_frames(T, N, dtype=np.float64): 12 | np.random.seed(98765) 13 | frames = pysptk.hanning(N) * np.random.randn(T, N) 14 | return frames.astype(np.float64) 15 | 16 | 17 | @pytest.mark.parametrize("order", [15, 20, 25]) 18 | @pytest.mark.parametrize("alpha", [0.0, 0.35, 0.41]) 19 | def test_mcep(order, alpha): 20 | x = windowed_dummy_data(1024) 21 | 22 | def __test(order, alpha): 23 | mc = pysptk.mcep(x, order, alpha) 24 | assert np.all(np.isfinite(mc)) 25 | 26 | __test(order, alpha) 27 | 28 | 29 | def test_mcep_broadcast(): 30 | # Test for broadcasting 31 | def __test_broadcast(dtype): 32 | frames = windowed_dummy_frames(100, 512, dtype=dtype) 33 | mc = pysptk.mcep(frames, 20, 0.41) 34 | assert np.all(np.isfinite(mc)) 35 | assert frames.shape[0] == mc.shape[0] 36 | 37 | for dtype in [np.float16, np.float32, np.float64]: 38 | __test_broadcast(dtype) 39 | 40 | 41 | def test_mcep_invalid_args(): 42 | x = windowed_dummy_data(1024) 43 | 44 | def __test_itype(itype=0): 45 | pysptk.mcep(x, itype=itype) 46 | 47 | with pytest.raises(ValueError): 48 | __test_itype(-1) 49 | with pytest.raises(ValueError): 50 | __test_itype(5) 51 | 52 | def __test_eps(etype=0, eps=0.0): 53 | pysptk.mcep(x, etype=etype, eps=eps) 54 | 55 | with pytest.raises(ValueError): 56 | __test_eps(0, -1.0) 57 | with pytest.raises(ValueError): 58 | __test_eps(-1) 59 | with pytest.raises(ValueError): 60 | __test_eps(-3) 61 | with pytest.raises(ValueError): 62 | __test_eps(1, -1.0) 63 | with pytest.raises(ValueError): 64 | __test_eps(2, 0.0) 65 | with pytest.raises(ValueError): 66 | __test_eps(2, 1.0) 67 | 68 | def __test_min_det(min_det): 69 | pysptk.mcep(x, min_det=min_det) 70 | 71 | with pytest.raises(ValueError): 72 | __test_min_det(-1.0) 73 | 74 | 75 | def test_mcep_failure(): 76 | with pytest.raises(RuntimeError): 77 | pysptk.mcep(np.ones(256), 40, 0.41) 78 | 79 | 80 | @pytest.mark.parametrize("order", [15, 20, 25]) 81 | @pytest.mark.parametrize("gamma", [0.0, -0.25, -0.5]) 82 | def test_gcep(order, gamma): 83 | x = windowed_dummy_data(1024) 84 | gc = pysptk.gcep(x, order, gamma) 85 | assert np.all(np.isfinite(gc)) 86 | 87 | 88 | def test_gcep_invalid_args(): 89 | x = windowed_dummy_data(1024) 90 | 91 | def __test_gamma(gamma): 92 | pysptk.gcep(x, gamma=gamma) 93 | 94 | with pytest.raises(ValueError): 95 | __test_gamma(0.1) 96 | with pytest.raises(ValueError): 97 | __test_gamma(-2.1) 98 | 99 | def __test_itype(itype=0): 100 | pysptk.gcep(x, itype=itype) 101 | 102 | with pytest.raises(ValueError): 103 | __test_itype(-1) 104 | with pytest.raises(ValueError): 105 | __test_itype(5) 106 | 107 | def __test_eps(etype=0, eps=0.0): 108 | pysptk.gcep(x, etype=etype, eps=eps) 109 | 110 | with pytest.raises(ValueError): 111 | __test_eps(0, -1.0) 112 | with pytest.raises(ValueError): 113 | __test_eps(-1) 114 | with pytest.raises(ValueError): 115 | __test_eps(-3) 116 | with pytest.raises(ValueError): 117 | __test_eps(1, -1.0) 118 | with pytest.raises(ValueError): 119 | __test_eps(2, -1.0) 120 | 121 | def __test_min_det(min_det): 122 | pysptk.gcep(x, min_det=min_det) 123 | 124 | with pytest.raises(ValueError): 125 | __test_min_det(-1.0) 126 | 127 | 128 | def test_gcep_failure(): 129 | with pytest.raises(RuntimeError): 130 | pysptk.gcep(np.ones(256), 40, 0.0) 131 | 132 | 133 | @pytest.mark.parametrize("order", [15, 20, 25]) 134 | @pytest.mark.parametrize("alpha", [0.0, 0.35, 0.41]) 135 | @pytest.mark.parametrize("gamma", [-0.5, -0.25, 0.0]) 136 | def test_mgcep(order, alpha, gamma): 137 | x = windowed_dummy_data(1024) 138 | 139 | mgc = pysptk.mgcep(x, order, alpha, gamma) 140 | assert np.all(np.isfinite(mgc)) 141 | 142 | 143 | def test_mgcep_invalid_args(): 144 | x = windowed_dummy_data(1024) 145 | 146 | def __test_gamma(gamma): 147 | pysptk.mgcep(x, gamma=gamma) 148 | 149 | with pytest.raises(ValueError): 150 | __test_gamma(0.1) 151 | with pytest.raises(ValueError): 152 | __test_gamma(-2.1) 153 | 154 | def __test_itype(itype=0): 155 | pysptk.mgcep(x, itype=itype) 156 | 157 | with pytest.raises(ValueError): 158 | __test_itype(-1) 159 | with pytest.raises(ValueError): 160 | __test_itype(5) 161 | 162 | def __test_eps(etype=0, eps=0.0): 163 | pysptk.mgcep(x, etype=etype, eps=eps) 164 | 165 | with pytest.raises(ValueError): 166 | __test_eps(0, -1.0) 167 | with pytest.raises(ValueError): 168 | __test_eps(-1) 169 | with pytest.raises(ValueError): 170 | __test_eps(-3) 171 | with pytest.raises(ValueError): 172 | __test_eps(1, -1.0) 173 | with pytest.raises(ValueError): 174 | __test_eps(2, -1.0) 175 | 176 | def __test_min_det(min_det): 177 | pysptk.mgcep(x, min_det=min_det) 178 | 179 | with pytest.raises(ValueError): 180 | __test_min_det(-1.0) 181 | 182 | def __test_otype(otype=0): 183 | pysptk.mgcep(x, otype=otype) 184 | 185 | with pytest.raises(ValueError): 186 | __test_otype(-1) 187 | with pytest.raises(ValueError): 188 | __test_otype(6) 189 | 190 | 191 | def test_mgcep_failure(): 192 | with pytest.raises(RuntimeError): 193 | pysptk.mgcep(np.ones(256)) 194 | 195 | 196 | @pytest.mark.parametrize("order", [15, 20, 25]) 197 | def test_uels(order): 198 | x = windowed_dummy_data(1024) 199 | 200 | c = pysptk.uels(x, order) 201 | assert np.all(np.isfinite(c)) 202 | 203 | 204 | def test_uels_invalid_args(): 205 | x = windowed_dummy_data(1024) 206 | 207 | def __test_itype(itype=0): 208 | pysptk.uels(x, itype=itype) 209 | 210 | with pytest.raises(ValueError): 211 | __test_itype(-1) 212 | with pytest.raises(ValueError): 213 | __test_itype(5) 214 | 215 | def __test_eps(etype=0, eps=0.0): 216 | pysptk.uels(x, etype=etype, eps=eps) 217 | 218 | with pytest.raises(ValueError): 219 | __test_eps(0, -1.0) 220 | with pytest.raises(ValueError): 221 | __test_eps(-1) 222 | with pytest.raises(ValueError): 223 | __test_eps(-3) 224 | with pytest.raises(ValueError): 225 | __test_eps(1, -1.0) 226 | with pytest.raises(ValueError): 227 | __test_eps(2, -1.0) 228 | 229 | 230 | def test_uels_failure(): 231 | with pytest.raises(RuntimeError): 232 | pysptk.uels(np.ones(256), 40) 233 | 234 | 235 | @pytest.mark.parametrize("order", [15, 20, 25]) 236 | def test_fftcep(order): 237 | x = windowed_dummy_data(1024) 238 | logsp = np.log(np.abs(np.fft.rfft(x)) + 1.0e-6) 239 | 240 | c = pysptk.fftcep(logsp, order) 241 | assert np.all(np.isfinite(c)) 242 | 243 | 244 | @pytest.mark.parametrize("order", [15, 20, 25]) 245 | def test_lpc(order): 246 | x = windowed_dummy_data(1024) 247 | 248 | a1 = pysptk.lpc(x, order, use_scipy=False) 249 | a2 = pysptk.lpc(x, order, use_scipy=True) 250 | a3 = pysptk.levdur(pysptk.acorr(x, order), use_scipy=False) 251 | a4 = pysptk.levdur(pysptk.acorr(x, order), use_scipy=True) 252 | 253 | assert np.all(np.isfinite(a1)) 254 | assert np.allclose(a1, a2) 255 | assert np.allclose(a1, a3) 256 | assert np.allclose(a1, a4) 257 | 258 | 259 | def test_lpc_invalid_args(): 260 | x = windowed_dummy_data(1024) 261 | 262 | def __test_min_det(min_det): 263 | pysptk.lpc(x, min_det=min_det, use_scipy=False) 264 | 265 | with pytest.raises(ValueError): 266 | __test_min_det(-1.0) 267 | 268 | 269 | def test_lpc_failure(): 270 | with pytest.raises(RuntimeError): 271 | pysptk.lpc(np.zeros(256), 40, use_scipy=False) 272 | -------------------------------------------------------------------------------- /tests/test_sptk.py: -------------------------------------------------------------------------------- 1 | def test_sptk(): 2 | assert 1 == 1 3 | -------------------------------------------------------------------------------- /tests/test_synthesis.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pysptk 3 | import pytest 4 | from pysptk.synthesis import Synthesizer 5 | 6 | 7 | def __dummy_source(): 8 | np.random.seed(98765) 9 | return np.random.randn(2 ** 14) 10 | 11 | 12 | def __dummy_windowed_frames(source, frame_len=512, hopsize=80): 13 | np.random.seed(98765) 14 | n_frames = int(len(source) / hopsize) + 1 15 | windowed = np.random.randn(n_frames, frame_len) * pysptk.blackman(frame_len) 16 | return 0.5 * 32768.0 * windowed 17 | 18 | 19 | @pytest.mark.parametrize("order", [20, 25]) 20 | @pytest.mark.parametrize("pd", [4, 5, 6, 7]) 21 | def test_LMADF(order, pd): 22 | from pysptk.synthesis import LMADF 23 | 24 | def __test_synthesis(filt): 25 | # dummy source excitation 26 | source = __dummy_source() 27 | 28 | hopsize = 80 29 | 30 | # dummy filter coef. 31 | windowed = __dummy_windowed_frames(source, frame_len=512, hopsize=hopsize) 32 | b = pysptk.mcep(windowed, filt.order, 0.0) 33 | 34 | # synthesis 35 | synthesizer = Synthesizer(filt, hopsize) 36 | y = synthesizer.synthesis(source, b) 37 | assert np.all(np.isfinite(y)) 38 | 39 | def __test(order, pd): 40 | __test_synthesis(LMADF(order, pd=pd)) 41 | 42 | __test(order, pd) 43 | 44 | 45 | def test_LMADF_corner_case(): 46 | from pysptk.synthesis import LMADF 47 | 48 | def __test_invalid_pade(pd): 49 | LMADF(20, pd=pd) 50 | 51 | with pytest.raises(ValueError): 52 | __test_invalid_pade(3) 53 | with pytest.raises(ValueError): 54 | __test_invalid_pade(8) 55 | 56 | 57 | @pytest.mark.parametrize("order", [20, 25]) 58 | @pytest.mark.parametrize("pd", [4, 5, 6, 7]) 59 | @pytest.mark.parametrize("alpha", [0.0, 0.41]) 60 | def test_MLSADF(order, pd, alpha): 61 | def __test_synthesis(filt): 62 | # dummy source excitation 63 | source = __dummy_source() 64 | 65 | hopsize = 80 66 | 67 | # dummy filter coef. 68 | windowed = __dummy_windowed_frames(source, frame_len=512, hopsize=hopsize) 69 | mc = pysptk.mcep(windowed, filt.order, filt.alpha) 70 | b = pysptk.mc2b(mc, filt.alpha) 71 | 72 | # synthesis 73 | synthesizer = Synthesizer(filt, hopsize) 74 | y = synthesizer.synthesis(source, b) 75 | assert np.all(np.isfinite(y)) 76 | 77 | # transpose 78 | synthesizer = Synthesizer(filt, hopsize, transpose=True) 79 | y = synthesizer.synthesis(source, b) 80 | assert np.all(np.isfinite(y)) 81 | 82 | from pysptk.synthesis import MLSADF 83 | 84 | def __test(order, alpha, pd): 85 | __test_synthesis(MLSADF(order, alpha, pd=pd)) 86 | 87 | __test(order, alpha, pd) 88 | 89 | 90 | def test_MLSADF_corner_case(): 91 | from pysptk.synthesis import MLSADF 92 | 93 | def __test_invalid_pade(pd): 94 | MLSADF(20, pd=pd) 95 | 96 | with pytest.raises(ValueError): 97 | __test_invalid_pade(3) 98 | with pytest.raises(ValueError): 99 | __test_invalid_pade(8) 100 | 101 | 102 | @pytest.mark.parametrize("order", [20, 25]) 103 | @pytest.mark.parametrize("stage", [2, 5, 10]) 104 | def test_GLSADF(order, stage): 105 | from pysptk.synthesis import GLSADF 106 | 107 | def __test_synthesis(filt): 108 | # dummy source excitation 109 | source = __dummy_source() 110 | 111 | hopsize = 80 112 | 113 | # dummy filter coef. 114 | windowed = __dummy_windowed_frames(source, frame_len=512, hopsize=hopsize) 115 | gamma = -1.0 / filt.stage 116 | mgc = pysptk.mgcep(windowed, filt.order, 0.0, gamma) 117 | b = pysptk.mgc2b(mgc, 0.0, gamma) 118 | 119 | # synthesis 120 | synthesizer = Synthesizer(filt, hopsize) 121 | y = synthesizer.synthesis(source, b) 122 | assert np.all(np.isfinite(y)) 123 | 124 | # transpose 125 | synthesizer = Synthesizer(filt, hopsize, transpose=True) 126 | y = synthesizer.synthesis(source, b) 127 | assert np.all(np.isfinite(y)) 128 | 129 | def __test(order, stage): 130 | __test_synthesis(GLSADF(order, stage)) 131 | 132 | __test(order, stage) 133 | 134 | def __test_invalid_stage(stage): 135 | GLSADF(20, stage=stage) 136 | 137 | 138 | def test_GLSADF_corner_case(): 139 | from pysptk.synthesis import GLSADF 140 | 141 | def __test_invalid_stage(stage): 142 | GLSADF(20, stage=stage) 143 | 144 | with pytest.raises(ValueError): 145 | __test_invalid_stage(-1) 146 | with pytest.raises(ValueError): 147 | __test_invalid_stage(0) 148 | 149 | 150 | @pytest.mark.parametrize("order", [20, 25]) 151 | @pytest.mark.parametrize("alpha", [0.0, 0.41]) 152 | @pytest.mark.parametrize("stage", [2, 5, 10]) 153 | def test_MGLSADF(order, alpha, stage): 154 | from pysptk.synthesis import MGLSADF 155 | 156 | def __test_synthesis(filt): 157 | # dummy source excitation 158 | source = __dummy_source() 159 | 160 | hopsize = 80 161 | 162 | # dummy filter coef. 163 | windowed = __dummy_windowed_frames(source, frame_len=512, hopsize=hopsize) 164 | gamma = -1.0 / filt.stage 165 | mgc = pysptk.mgcep(windowed, filt.order, filt.alpha, gamma) 166 | b = pysptk.mgc2b(mgc, filt.alpha, gamma) 167 | 168 | # synthesis 169 | synthesizer = Synthesizer(filt, hopsize) 170 | y = synthesizer.synthesis(source, b) 171 | assert np.all(np.isfinite(y)) 172 | 173 | # transpose 174 | synthesizer = Synthesizer(filt, hopsize, transpose=True) 175 | y = synthesizer.synthesis(source, b) 176 | assert np.all(np.isfinite(y)) 177 | 178 | def __test(order, alpha, stage): 179 | __test_synthesis(MGLSADF(order, alpha, stage)) 180 | 181 | __test(order, alpha, stage) 182 | 183 | 184 | def test_MGLSADF_corner_case(): 185 | from pysptk.synthesis import MGLSADF 186 | 187 | def __test_invalid_stage(stage): 188 | MGLSADF(20, stage=stage) 189 | 190 | with pytest.raises(ValueError): 191 | __test_invalid_stage(-1) 192 | with pytest.raises(ValueError): 193 | __test_invalid_stage(0) 194 | 195 | 196 | def test_AllZeroDF(): 197 | pass 198 | 199 | def __test_synthesis(filt): 200 | # dummy source excitation 201 | source = __dummy_source() 202 | 203 | hopsize = 80 204 | 205 | # dummy filter coef. 206 | windowed = __dummy_windowed_frames(source, frame_len=512, hopsize=hopsize) 207 | lpc = pysptk.lpc(windowed, filt.order) 208 | lpc[:, 0] = 0 209 | b = -lpc 210 | 211 | # synthesis 212 | synthesizer = Synthesizer(filt, hopsize) 213 | y = synthesizer.synthesis(source, b) 214 | assert np.all(np.isfinite(y)) 215 | 216 | # transpose 217 | synthesizer = Synthesizer(filt, hopsize, transpose=True) 218 | y = synthesizer.synthesis(source, b) 219 | assert np.all(np.isfinite(y)) 220 | 221 | 222 | @pytest.mark.parametrize("order", [20, 25]) 223 | def test_AllPoleDF(order): 224 | from pysptk.synthesis import AllPoleDF 225 | 226 | def __test_synthesis(filt): 227 | # dummy source excitation 228 | source = __dummy_source() 229 | 230 | hopsize = 80 231 | 232 | # dummy filter coef. 233 | windowed = __dummy_windowed_frames(source, frame_len=512, hopsize=hopsize) 234 | lpc = pysptk.lpc(windowed, filt.order) 235 | 236 | # make sure lpc has loggain 237 | lpc[:, 0] = np.log(lpc[:, 0]) 238 | 239 | # synthesis 240 | synthesizer = Synthesizer(filt, hopsize) 241 | y = synthesizer.synthesis(source, lpc) 242 | assert np.all(np.isfinite(y)) 243 | 244 | # transpose 245 | synthesizer = Synthesizer(filt, hopsize, transpose=True) 246 | y = synthesizer.synthesis(source, lpc) 247 | assert np.all(np.isfinite(y)) 248 | 249 | def __test_synthesis_levdur(filt): 250 | # dummy source excitation 251 | source = __dummy_source() 252 | 253 | hopsize = 80 254 | 255 | # dummy filter coef. 256 | windowed = __dummy_windowed_frames(source, frame_len=512, hopsize=hopsize) 257 | c = pysptk.mcep(windowed, filt.order) 258 | a = pysptk.c2acr(c) 259 | lpc = pysptk.levdur(a) 260 | lpc2 = pysptk.levdur(a, use_scipy=True) 261 | assert np.allclose(lpc, lpc2) 262 | 263 | # make sure lpc has loggain 264 | lpc[:, 0] = np.log(lpc[:, 0]) 265 | 266 | # synthesis 267 | synthesizer = Synthesizer(filt, hopsize) 268 | y = synthesizer.synthesis(source, lpc) 269 | assert np.all(np.isfinite(y)) 270 | 271 | def __test(order): 272 | __test_synthesis(AllPoleDF(order)) 273 | __test_synthesis_levdur(AllPoleDF(order)) 274 | 275 | __test(order) 276 | 277 | 278 | @pytest.mark.parametrize("order", [20, 25]) 279 | def test_AllPoleLatticeDF(order): 280 | from pysptk.synthesis import AllPoleLatticeDF 281 | 282 | def __test_synthesis(filt): 283 | # dummy source excitation 284 | source = __dummy_source() 285 | 286 | hopsize = 80 287 | 288 | # dummy filter coef. 289 | windowed = __dummy_windowed_frames(source, frame_len=512, hopsize=hopsize) 290 | lpc = pysptk.lpc(windowed, filt.order) 291 | par = pysptk.lpc2par(lpc) 292 | 293 | # make sure par has loggain 294 | par[:, 0] = np.log(par[:, 0]) 295 | 296 | # synthesis 297 | synthesizer = Synthesizer(filt, hopsize) 298 | y = synthesizer.synthesis(source, par) 299 | assert np.all(np.isfinite(y)) 300 | 301 | __test_synthesis(AllPoleLatticeDF(order)) 302 | 303 | 304 | @pytest.mark.parametrize("order", [20, 25]) 305 | def test_LSPDF(order): 306 | from pysptk.synthesis import LSPDF 307 | 308 | def __test_synthesis(filt): 309 | # dummy source excitation 310 | source = __dummy_source() 311 | 312 | hopsize = 80 313 | 314 | # dummy filter coef. 315 | windowed = __dummy_windowed_frames(source, frame_len=512, hopsize=hopsize) 316 | lpc = pysptk.lpc(windowed, filt.order) 317 | lsp = pysptk.lpc2lsp(lpc) 318 | # make sure lsp has loggain 319 | lsp[:, 0] = np.log(lsp[:, 0]) 320 | 321 | # synthesis 322 | synthesizer = Synthesizer(filt, hopsize) 323 | y = synthesizer.synthesis(source, lsp) 324 | assert np.all(np.isfinite(y)) 325 | 326 | __test_synthesis(LSPDF(order)) 327 | -------------------------------------------------------------------------------- /tests/test_synthesis_filters.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pysptk 3 | import pytest 4 | 5 | 6 | def __test_filt_base(f, order, delay, *args): 7 | np.random.seed(98765) 8 | dummy_input = np.random.rand(1024) 9 | dummy_mgc = np.random.rand(order + 1) 10 | 11 | for x in dummy_input: 12 | assert np.isfinite(f(x, dummy_mgc, *args, delay=delay)) 13 | assert np.all(np.isfinite(delay)) 14 | 15 | 16 | @pytest.mark.parametrize("order", [20, 25, 30]) 17 | def test_poledf(order): 18 | delay = pysptk.poledf_delay(order) 19 | __test_filt_base(pysptk.poledf, order, delay) 20 | __test_filt_base(pysptk.poledft, order, delay) 21 | 22 | 23 | def test_poledf_invalid_delay_length(): 24 | with pytest.raises(ValueError): 25 | pysptk.poledf(0.0, np.ones(10), np.ones(1)) 26 | 27 | 28 | @pytest.mark.parametrize("order", [20, 25, 30]) 29 | @pytest.mark.parametrize("pd", [4, 5]) 30 | def test_lmadf(order, pd): 31 | delay = pysptk.lmadf_delay(order, pd) 32 | __test_filt_base(pysptk.lmadf, order, delay, pd) 33 | 34 | 35 | def test_lmadf_invalid_delay_length(): 36 | with pytest.raises(ValueError): 37 | pysptk.lmadf(0.0, np.ones(10), 5, np.ones(1)) 38 | 39 | 40 | def test_lmadf_invalid_pade(): 41 | with pytest.raises(ValueError): 42 | pysptk.lmadf(0.0, np.ones(10), 3, np.ones(1)) 43 | 44 | 45 | @pytest.mark.parametrize("order", [20, 25, 30]) 46 | def test_lspdf(order): 47 | delay = pysptk.lspdf_delay(order) 48 | __test_filt_base(pysptk.lspdf, order, delay) 49 | 50 | 51 | def test_lspdf_invalid_delay_length(): 52 | def __test(length): 53 | pysptk.lspdf(0.0, np.ones(length), np.ones(1)) 54 | 55 | # even 56 | with pytest.raises(ValueError): 57 | __test(10) 58 | # odd 59 | with pytest.raises(ValueError): 60 | __test(9) 61 | 62 | 63 | @pytest.mark.parametrize("order", [20, 25, 30]) 64 | def test_ltcdf(order): 65 | delay = pysptk.ltcdf_delay(order) 66 | __test_filt_base(pysptk.ltcdf, order, delay) 67 | 68 | 69 | def test_ltcdf_invalid_delay_length(): 70 | with pytest.raises(ValueError): 71 | pysptk.ltcdf(0.0, np.ones(10), np.ones(1)) 72 | 73 | 74 | @pytest.mark.parametrize("order", [20, 22, 25]) 75 | @pytest.mark.parametrize("stage", [1, 2, 3, 4, 5, 6]) 76 | def test_glsadf(order, stage): 77 | delay = pysptk.glsadf_delay(order, stage) 78 | __test_filt_base(pysptk.glsadf, order, delay, stage) 79 | __test_filt_base(pysptk.glsadft, order, delay, stage) 80 | 81 | 82 | def test_glsadf_invalid_delay_length(): 83 | with pytest.raises(ValueError): 84 | pysptk.glsadf(0.0, np.ones(10), 1, np.ones(1)) 85 | 86 | 87 | def test_glsadf_invalid_stage(): 88 | with pytest.raises(ValueError): 89 | pysptk.glsadf(0.0, np.ones(10), 0, np.ones(1)) 90 | 91 | 92 | @pytest.mark.parametrize("order", [20, 25, 30]) 93 | @pytest.mark.parametrize("alpha", [0.0, 0.35, 0.5]) 94 | @pytest.mark.parametrize("pd", [4, 5]) 95 | def test_mlsadf(order, alpha, pd): 96 | delay = pysptk.mlsadf_delay(order, pd) 97 | __test_filt_base(pysptk.mlsadf, order, delay, alpha, pd) 98 | __test_filt_base(pysptk.mlsadft, order, delay, alpha, pd) 99 | 100 | 101 | def test_mlsadf_invalid_delay_length(): 102 | with pytest.raises(ValueError): 103 | pysptk.mlsadf(0.0, np.ones(10), 0.41, 5, np.ones(1)) 104 | 105 | 106 | def test_mlsadf_invalid_pade(): 107 | with pytest.raises(ValueError): 108 | pysptk.mlsadf(0.0, np.ones(10), 0.41, 3, np.ones(1)) 109 | 110 | 111 | @pytest.mark.parametrize("order", [20, 25, 30]) 112 | @pytest.mark.parametrize("alpha", [0.0, 0.35, 0.5]) 113 | @pytest.mark.parametrize("stage", [1, 2, 3, 4, 5, 6]) 114 | def test_mglsadf(order, alpha, stage): 115 | delay = pysptk.mglsadf_delay(order, stage) 116 | __test_filt_base(pysptk.mglsadf, order, delay, alpha, stage) 117 | __test_filt_base(pysptk.mglsadft, order, delay, alpha, stage) 118 | 119 | 120 | def test_mglsadf_invalid_delay_length(): 121 | with pytest.raises(ValueError): 122 | pysptk.mglsadf(0.0, np.ones(10), 0.41, 15, np.ones(1)) 123 | 124 | 125 | def test_mglsadf_invalid_stage(): 126 | with pytest.raises(ValueError): 127 | pysptk.mglsadf(0.0, np.ones(10), 0.41, 0, np.ones(1)) 128 | -------------------------------------------------------------------------------- /tests/test_utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pysptk 3 | import pytest 4 | from pysptk.util import apply_along_last_axis, automatic_type_conversion, mcepalpha 5 | 6 | 7 | def test_assert_gamma(): 8 | def __test(gamma): 9 | pysptk.util.assert_gamma(gamma) 10 | 11 | for gamma in [-2.0, 0.1]: 12 | with pytest.raises(ValueError): 13 | __test(gamma) 14 | 15 | 16 | def test_assert_pade(): 17 | def __test(pade): 18 | pysptk.util.assert_pade(pade) 19 | 20 | for pade in [3, 8]: 21 | with pytest.raises(ValueError): 22 | __test(pade) 23 | 24 | 25 | def test_assert_fftlen(): 26 | def __test(fftlen): 27 | pysptk.util.assert_fftlen(fftlen) 28 | 29 | for fftlen in [255, 257]: 30 | with pytest.raises(ValueError): 31 | __test(fftlen) 32 | 33 | 34 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 35 | @pytest.mark.parametrize("alpha", [0.35, 0.41, 0.5]) 36 | def test_phidf(order, alpha): 37 | np.random.seed(98765) 38 | dummy_input = np.random.rand(64) 39 | delay = np.zeros(order + 1) 40 | for x in dummy_input: 41 | pysptk.phidf(x, order, alpha, delay) 42 | assert np.all(np.isfinite(delay)) 43 | 44 | 45 | @pytest.mark.parametrize("order", [15, 20, 25, 30]) 46 | def test_lspcheck(order): 47 | np.random.seed(98765) 48 | lsp = np.random.rand(order + 1) 49 | pysptk.lspcheck(lsp) 50 | # TODO: valid check 51 | 52 | 53 | def test_example_audio_file(): 54 | from os.path import exists 55 | 56 | path = pysptk.util.example_audio_file() 57 | assert exists(path) 58 | 59 | 60 | def test_mcepalpha(): 61 | assert np.isclose(mcepalpha(8000), 0.312) 62 | assert np.isclose(mcepalpha(11025), 0.357) 63 | assert np.isclose(mcepalpha(16000), 0.41) 64 | assert np.isclose(mcepalpha(22050), 0.455) 65 | assert np.isclose(mcepalpha(44100), 0.544) 66 | assert np.isclose(mcepalpha(48000), 0.554) 67 | 68 | 69 | def test_automatic_type_conversion(): 70 | @automatic_type_conversion 71 | def f(x): 72 | return x 73 | 74 | for dtype in [np.float32, np.float16, np.float64]: 75 | x = np.ones(10, dtype=dtype) 76 | y = f(x) 77 | assert y.dtype == x.dtype 78 | y = f(x=x) 79 | assert y.dtype == x.dtype 80 | 81 | 82 | def test_apply_along_last_axis(): 83 | @apply_along_last_axis 84 | def f(x): 85 | assert x.ndim == 1 86 | return x[: len(x) // 2] + np.arange(len(x) // 2) 87 | 88 | for shape in [(10,), (2, 10), (2, 2, 10)]: 89 | x = np.ones(shape) 90 | y = f(x) 91 | xshape = x.shape 92 | yshape = y.shape 93 | assert len(xshape) == len(yshape) 94 | assert xshape[-1] // 2 == yshape[-1] 95 | y = f(x=x) 96 | yshape = y.shape 97 | assert len(xshape) == len(yshape) 98 | assert xshape[-1] // 2 == yshape[-1] 99 | 100 | # manually expand 1-loop 101 | x = np.ones((2, 10), dtype=np.float64) 102 | y = np.empty((2, 5), dtype=np.float64) 103 | for i in range(len(x)): 104 | y[i] = f(x[i]) 105 | yhat = f(x) 106 | assert np.allclose(yhat, y) 107 | 108 | # expand 2-loop 109 | x = np.ones((2, 2, 10), dtype=np.float64) 110 | y = np.empty((2, 2, 5), dtype=np.float64) 111 | for i in range(len(x)): 112 | for j in range(len(x[i])): 113 | y[i][j] = f(x[i][j]) 114 | yhat = f(x) 115 | assert np.allclose(yhat, y) 116 | 117 | 118 | def test_multiple_decorators(): 119 | @apply_along_last_axis 120 | @automatic_type_conversion 121 | def half_vec(x): 122 | assert x.ndim == 1 123 | return x[: len(x) // 2] 124 | 125 | for shape in [(10,), (2, 10), (2, 2, 10)]: 126 | for dtype in [np.float32, np.float16, np.float64]: 127 | x = np.ones(shape, dtype=dtype) 128 | y = half_vec(x) 129 | xshape = x.shape 130 | yshape = y.shape 131 | assert len(xshape) == len(yshape) 132 | assert xshape[-1] // 2 == yshape[-1] 133 | assert x.dtype == y.dtype 134 | -------------------------------------------------------------------------------- /tests/test_window.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | from pysptk import bartlett, blackman, hamming, hanning, rectangular, trapezoid 4 | 5 | 6 | @pytest.mark.parametrize( 7 | "f", [blackman, hanning, hamming, bartlett, trapezoid, rectangular] 8 | ) 9 | @pytest.mark.parametrize("n", [16, 128, 256, 1024, 2048, 4096]) 10 | def test_windows(f, n): 11 | def __test(f, N, normalize): 12 | w = f(N, normalize) 13 | assert np.all(np.isfinite(w)) 14 | 15 | __test(f, n, 1) 16 | 17 | 18 | def test_windows_corner_case(): 19 | def __test(f, N, normalize): 20 | f(N, normalize) 21 | 22 | # unsupported normalize flags 23 | for f in [blackman, hanning, hamming, bartlett, trapezoid, rectangular]: 24 | with pytest.raises(ValueError): 25 | __test(f, 256, -1) 26 | with pytest.raises(ValueError): 27 | __test(f, 256, 3) 28 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | ignore = E266,E305,E402,E721,E741,F401,F403,F405,F811,F821,F841,F999,W504,W605 4 | exclude = docs/,examples,build,dist,.eggs,lib 5 | --------------------------------------------------------------------------------