PyWorld wraps the WORLD vocoder as a compiled Cython extension
A Python wrapper for the high-quality vocoder "World"
At a glance
- What is it?
- Python-Wrapper-for-World-Vocoder builds Morise's WORLD vocoder from C++ sources into a Cython extension named pyworld, exposing pitch extraction, spectral envelope analysis and resynthesis as NumPy arrays. It suits speech researchers who need the three parameterisation components in Python, and it fails outright on 8 kHz audio.
- Who is it for?
- Adopt PyWorld when your pipeline needs WORLD's f0, sp and ap parameters inside Python and you can build a C++ extension, since the wrapper compiles the upstream C++ sources rather than shipping a wheel for every platform. Do not adopt it for telephone band audio, because the documentation states that applying WORLD to 8 kHz speech will fail, and do not expect a pure Python fallback if the build breaks.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 64 days ago.
- What is it written in?
- Mainly Cython, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Three parameters describe the speech signal, and this package exposes all of them
The WORLD vocoder parameterises speech into three components, and understanding that split explains the shape of the API. The first is f0, the pitch contour. The second is sp, the harmonic spectral envelope. The third is ap, the aperiodic spectral envelope, which is expressed relative to the harmonic one. Because the representation is invertible, the same library both analyses and synthesises. The wrapper exposes the individual stages so you can choose your own combination:
import pyworld as pw
_f0, t = pw.dio(x, fs) # raw pitch extractor
f0 = pw.stonemask(x, _f0, t, fs) # pitch refinement
sp = pw.cheaptrick(x, f0, t, fs) # extract smoothed spectrogram
ap = pw.d4c(x, f0, t, fs) # extract aperiodicity
y = pw.synthesize(f0, sp, ap, fs) # synthesize an utterance using the parametersThe order matters. dio produces a rough pitch track and times, stonemask refines that track against the signal, and cheaptrick and d4c both take the refined f0 as input. There is also a convenience path that runs the whole chain with default arguments:
# Convert speech into features (using default arguments)
f0, sp, ap = pw.wav2world(x, fs)The documentation notes that the default arguments of these functions can be changed and points to help for the details, so the surface is larger than the five calls shown here.
The extension compiles the upstream C++ sources rather than vendoring binaries
The build is where this project differs from a thin binding. The package is named pyworld, and the primary language of the repository is Cython. The setup script globs the C++ sources under lib/World/src and compiles them together with the Cython module pyworld/pyworld.pyx into a single extension module called pyworld.pyworld, with the numpy headers added to the include path. The build system declared in pyproject.toml requires setuptools, cython, and numpy, with numpy>=2 required on Python 3.9 and above and oldest-supported-numpy below that. A cython pin of less than 3.1.0 applies to Python versions below 3.9. The runtime install requirements are just numpy, with importlib-metadata pulled in for Python below 3.8. The practical consequence is that there is no prebuilt binary to download for an unusual platform, so a compiler and the C++ sources are part of the install. The repository also carries a .gitmodules file, which is how the upstream WORLD code is brought in as a submodule.
Installing from pip, or building the submodule yourself
The shortest route is the published package:
pip install pyworldThe documentation suggests using virtualenv or conda as the best practice, and for a source build it gives a sequence that clones the repository, initialises the submodule and installs the dependencies:
git clone https://github.com/JeremyCCHsu/Python-Wrapper-for-World-Vocoder.git
cd Python-Wrapper-for-World-Vocoder
git submodule update --init
pip install -U pip
pip install -r requirements.txt
pip install .The submodule step is the one that matters: the documentation states that it automatically clones Morise's World Vocoder in its C++ version, and skipping it leaves the build without the sources it compiles. After installing, validation is a run of the bundled demo:
cd demo
python demo.pyYou should see results appear in the test/ directory, which is where the demo writes its output. The documentation also advises against writing and executing your own code inside the Python-Wrapper-for-World-Vocoder folder while the project is in its current state, which is worth honouring because the demo directory and the source tree share a filesystem.
The 8 kHz limit is the failure mode to plan around
The single most important constraint is stated in the notice section: the WORLD vocoder is designed for speech sampled at 16 kHz or above, and applying it to 8 kHz speech will fail. The documentation links a possible workaround in an issue on the repository, so the path exists, but the default answer is that this wrapper is not the right tool for telephone band audio. A second notice is softer but operationally useful: when the signal to noise ratio is low, extracting pitch with harvest instead of dio is the better option. That is a direct hint about where the analysis breaks down, since dio is a fast approximation and harvest is the slower, more careful tracker. If you are working on noisy recordings, the fix is a different front end rather than different post-processing. A third point is about sampling rate handling in general: the wrapper takes the sampling frequency as an argument to every call, so a mismatch between the file and the fs you pass will produce garbage rather than an exception.
Audio input and output are the fragile part of the demo
Troubleshooting in this repository is unusually specific, and most of it concerns audio I/O rather than the vocoder itself. The common error is library not found: sndfile, which is fixed by installing libsoundfile1 with apt-get. The documentation also describes replacing pysoundfile with scipy or librosa, with a warning that modification is needed. For librosa the changes are to load with dtype=np.float64 and to write with output.write_wav, and the note is to pass the dtype argument so the values come back as double rather than float32. For scipy the work is larger: you have to write your own utility function, because scipy.io.wavfile.read returns short values and scipy.io.wavfile.write needs to be called instead. There is a second environment gotcha for remote Linux servers, where the demo may need a non-interactive matplotlib backend:
import matplotlib
matplotlib.use('Agg')The demo directory holds demo.py and an utterance folder, and the results land in test/. If you plan to use this in a headless pipeline, the backend line and the soundfile dependency are the two things to settle first.
Version pinning and the Cython upgrade note
The version string in setup.py reads 0.3.6, and there are no GitHub releases, so the commit history is the only release signal. The last push was on 2026-08-20 and the repository is not archived. The troubleshooting section carries one dependency note that has aged: it says to upgrade Cython to 0.24, with the parenthetical that the author failed to build it on Cython 0.20.1post0, and instructs readers to download Cython from its site and install it with python setup.py install because pip install Cython did not give the expected result. The build configuration has since moved on and now declares cython as a build requirement, so the old advice no longer describes how the package resolves its build dependency. If you hit a Cython compilation error, the place to look first is the pyproject.toml build requirement rather than the README note. Older interpreters also carry a constraint: cython<3.1.0 applies below Python 3.9, and numpy is capped at oldest-supported-numpy on those versions, so Python 3.7 and 3.8 users get a different toolchain than everyone else.
The alternative is to call the C++ library yourself
There is a straightforward alternative, and it is the one this wrapper was written to avoid. You can build the WORLD C++ sources directly and call them through ctypes, cffi or a hand written Cython module of your own, which gives the same three parameters with none of the packaging decisions above. The difference in approach is where the maintenance burden sits. The upstream project is where the algorithm changes, and a wrapper like this one has to absorb the churn of Cython versions, NumPy releases, Python version support and platform-specific builds, and the README reflects that history in its troubleshooting notes. This wrapper wins when you want an installable pip package with a stable import name, and the acknowledgement section credits an earlier pure Python implementation whose world.py inspired the project, which is a reminder that a third option exists: a Python port without compilation, at the cost of speed. If your data volume is small and you value an easy install over throughput, that trade may be the better one.
Editorial conclusion
Adopt PyWorld when your pipeline needs WORLD's f0, sp and ap parameters inside Python and you can build a C++ extension, since the wrapper compiles the upstream C++ sources rather than shipping a wheel for every platform. Do not adopt it for telephone band audio, because the documentation states that applying WORLD to 8 kHz speech will fail, and do not expect a pure Python fallback if the build breaks. Verify first that your NumPy version matches the build requirement of numpy>=2 on Python 3.9 and above, that a compiler toolchain is present, and that libsndfile is installed if you intend to run the demo, since a missing library surfaces as a sndfile error at runtime.
Frequently asked questions
How do I extract pitch and spectral features with PyWorld?
The individual stages are pw.dio for raw pitch extraction, pw.stonemask to refine it, pw.cheaptrick for the smoothed spectrogram and pw.d4c for aperiodicity, followed by pw.synthesize to resynthesise. The convenience function pw.wav2world returns f0, sp and ap in one call with default arguments.
Can PyWorld process 8 kHz audio?
The documentation states that the WORLD vocoder is designed for speech sampled at 16 kHz or higher and that applying it to 8 kHz speech will fail, with a possible workaround discussed in a linked issue. Plan on resampling to 16 kHz or more instead.
Why does the build fail with a library not found: sndfile error?
That error comes from the audio I/O layer used by the demo rather than from the vocoder itself. The documentation suggests installing libsoundfile1 with apt-get, or replacing pysoundfile with scipy or librosa, which requires code changes since scipy.io.wavfile.read returns short values.
Do I need to clone the WORLD C++ source to install PyWorld?
For a source build, yes. The documented sequence includes git submodule update --init, and the documentation states that this automatically clones Morise's World Vocoder in its C++ version, since the extension compiles the sources found under lib/World/src.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jeremycchsu-python-wrapper-for-world-vocoder)Was this useful?