diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 5688362..e102fb2 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -25,8 +25,8 @@ jobs: - name: Installing MBROLA run: | - sudo /bin/bash mbrola/install.sh + sudo /bin/bash src/install.sh - name: Testing with Pytest run: | - uv run pytest --cov=mbrola --cov-report=term-missing + uv run pytest --cov=src --cov-report=term-missing diff --git a/.gitignore b/.gitignore index 93fa443..1eb147c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,9 +21,11 @@ sdist/ var/ wheels/ share/python-wheels/ -*.egg-info/ +/*.egg-info +/*.egg-info +src/*.egg-info + .installed.cfg -*.egg MANIFEST # PyInstaller diff --git a/Dockerfile b/Dockerfile index 15e0cfd..3d8a6d6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,8 @@ -FROM python:3.12 +FROM ubuntu:22.04 WORKDIR /project ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y curl git build-essential gcc python3 COPY mbrola/install.sh /install.sh -RUN apt-get update && apt-get install -y git build-essential gcc RUN git config --global core.compression 0 -RUN RUN chmod +x /install.sh && /install.sh COPY mbrola/mbrola.py /project/ \ No newline at end of file diff --git a/README.md b/README.md index 87de7fd..1fc44a1 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ A Python interface for the [MBROLA](https://github.com/numediart/MBROLA) speech synthesizer, enabling programmatic creation of MBROLA-compatible phoneme files and automated audio synthesis. This module validates phoneme, duration, and pitch sequences, generates `.pho` files, and can call the MBROLA executable to synthesize speech audio from text-like inputs. -> **References:** -> Dutoit, T., Pagel, V., Pierret, N., Bataille, F., & Van der Vrecken, O. (1996, October). -> The MBROLA project: Towards a set of high quality speech synthesizers free of use for non commercial purposes. -> In Proceeding of Fourth International Conference on Spoken Language Processing. ICSLP'96 (Vol. 3, pp. 1393-1396). IEEE. +> **References:** +> Dutoit, T., Pagel, V., Pierret, N., Bataille, F., & Van der Vrecken, O. (1996, October). +> The MBROLA project: Towards a set of high quality speech synthesizers free of use for non commercial purposes. +> In Proceeding of Fourth International Conference on Spoken Language Processing. ICSLP'96 (Vol. 3, pp. 1393-1396). IEEE. > [https://doi.org/10.1109/ICSLP.1996.607874](https://doi.org/10.1109/ICSLP.1996.607874) ## Features @@ -42,21 +42,21 @@ pip install mbrola import mbrola # Create an MBROLA object -house = mbrola.MBROLA( - word="house", - phon=["h", "a", "U", "s"], +caffe = MBROLA( + word="caffè", + phon=["k", "a", "f", "f", "E1"], durations=100, # or [100, 120, 100, 110] - pitch=[200, [200, 50, 200], 200, 100] + pitch=[100, [200, 50, 200], 100, 100, 200] ) # Display phoneme sequence -print(house) +print(caffe) # Export PHO file -house.export_pho("house.pho") +caffe.export_pho("caffe.pho") # Synthesize and save audio (WAV file) -house.make_sound("house.wav", voice="it4") +caffe.make_sound("caffe.wav", voice="it4") ``` The module uses the MBROLA command line tool under the hood. Ensure MBROLA is installed and available in your system path, or WSL if on Windows. @@ -71,4 +71,3 @@ The module uses the MBROLA command line tool under the hood. Ensure MBROLA is in ## License `pymbrola` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license. - diff --git a/mbrola/py.typed b/mbrola/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/pyproject.toml b/pyproject.toml index 0d4bd68..dd9ef46 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mbrola" -version = "0.2.0" +version = "0.2.1" description = 'A Python front-end for the MBROLA speech synthesizer' readme = "README.md" requires-python = ">=3.12" @@ -41,7 +41,7 @@ publish-url = "https://pypi.org/" explicit = true [tool.hatch.version] -path = "mbrola/__about__.py" +path = "src/__about__.py" [tool.hatch.envs.types] extra-dependencies = [ @@ -54,16 +54,18 @@ extra-dependencies = [ python = ["3.10", "3.11"] [tool.hatch.envs.types.scripts] -check = "mypy --install-types --non-interactive {args:mbrola tests}" +check = "mypy --install-types --non-interactive {args:src tests}" [tool.coverage.run] -source_pkgs = ["mbrola", "tests"] +source_pkgs = ["src", "tests"] branch = true parallel = true omit = [ - "mbrola/__about__.py", + "src/__about__.py", ] +[tool.hatch.build] +sources = ["src"] [tool.hatch.build.targets.sdist] exclude = [ @@ -85,7 +87,7 @@ exclude = [ addopts = "--maxfail=1 --cov=testing_demo" [tool.coverage.paths] -pymbrola = ["mbrola", "*/pymbrola/mbrola"] +pymbrola = ["src"] tests = ["tests", "*/pymbrola/tests"] [tool.coverage.report] diff --git a/mbrola/__about___.py b/src/__about___.py similarity index 100% rename from mbrola/__about___.py rename to src/__about___.py diff --git a/mbrola/__init__.py b/src/__init__.py similarity index 100% rename from mbrola/__init__.py rename to src/__init__.py diff --git a/mbrola/install.sh b/src/install.sh similarity index 98% rename from mbrola/install.sh rename to src/install.sh index f88cd19..c0c3e75 100644 --- a/mbrola/install.sh +++ b/src/install.sh @@ -21,7 +21,7 @@ fi # Download and unzip MBROLA FNAME="mbrola-${RELEASE}.tar.gz" curl -L https://github.com/${REPO}/archive/refs/tags/${RELEASE}.tar.gz > ${FNAME} -tar -xf ${FNAME} +tar -xvf ${FNAME} # Compile MBROLA cd MBROLA-${RELEASE} diff --git a/src/mbrola.egg-info/PKG-INFO b/src/mbrola.egg-info/PKG-INFO new file mode 100644 index 0000000..32bb880 --- /dev/null +++ b/src/mbrola.egg-info/PKG-INFO @@ -0,0 +1,97 @@ +Metadata-Version: 2.4 +Name: mbrola +Version: 0.2.1 +Summary: A Python front-end for the MBROLA speech synthesizer +Author-email: Gonzalo Garcia-Castro +License-Expression: MIT +Project-URL: Documentation, https://github.com/gongcastro/pymbrola#readme +Project-URL: Issues, https://github.com/gongcastro/pymbrola/issues +Project-URL: Source, https://github.com/gongcastro/pymbrola +Classifier: Development Status :: 4 - Beta +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Requires-Python: >=3.12 +Description-Content-Type: text/markdown +License-File: LICENSE +Requires-Dist: pytest>=8.3.5 +Dynamic: license-file + +# pymbrola + +[![PyPI - Version](https://img.shields.io/pypi/v/mbrola.svg)](https://pypi.org/project/mbrola) +[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/mbrola.svg)](https://pypi.org/project/mbrola) + +----- + +A Python interface for the [MBROLA](https://github.com/numediart/MBROLA) speech synthesizer, enabling programmatic creation of MBROLA-compatible phoneme files and automated audio synthesis. This module validates phoneme, duration, and pitch sequences, generates `.pho` files, and can call the MBROLA executable to synthesize speech audio from text-like inputs. + +> **References:** +> Dutoit, T., Pagel, V., Pierret, N., Bataille, F., & Van der Vrecken, O. (1996, October). +> The MBROLA project: Towards a set of high quality speech synthesizers free of use for non commercial purposes. +> In Proceeding of Fourth International Conference on Spoken Language Processing. ICSLP'96 (Vol. 3, pp. 1393-1396). IEEE. +> [https://doi.org/10.1109/ICSLP.1996.607874](https://doi.org/10.1109/ICSLP.1996.607874) + +## Features + +- **Front-end to MBROLA:** Easily create `.pho` files and synthesize audio with Python. +- **Input validation:** Prevents invalid file and phoneme sequence errors. +- **Customizable:** Easily set phonemes, durations, pitch contours, and leading/trailing silences. +- **Cross-platform (Linux/WSL):** Automatically detects and adapts to Linux or Windows Subsystem for Linux environments. + +## Requirements + +- Python 3.8+ +- [MBROLA binary](https://github.com/numediart/MBROLA) installed and available in your system path, or via WSL for Windows users. To install MBROLA in your UBUNTU or WSL instance, run the [mbrola/install.sh] script. A [Docker image](https://hub.docker.com/repository/docker/gongcastro/mbrola/general) of Ubuntu 22.04 with a ready-to-go installation of MBROLA is available, for convenience. +- MBROLA voices (e.g., `it4`) must be installed at `/usr/share/mbrola//`. + +## Installation + +MBROLA is currently available only on Linux-based systems like Ubuntu, or on Windows via the [Windows Susbsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install). Install MBROLA in your machine following the instructions in the [MBROLA repository](https://github.com/numediart/MBROLA). If you are using WSL, install MBROLA in WSL. After this, you should be ready to install **pymbrola** using pip. + +```console +pip install mbrola +``` + +## Usage + +### Synthesize a Word + +```python +import mbrola + +# Create an MBROLA object +caffe = MBROLA( + word="caffè", + phon=["k", "a", "f", "f", "E1"], + durations=100, # or [100, 120, 100, 110] + pitch=[100, [200, 50, 200], 100, 100, 200] +) + +# Display phoneme sequence +print(caffe) + +# Export PHO file +caffe.export_pho("caffe.pho") + +# Synthesize and save audio (WAV file) +caffe.make_sound("caffe.wav", voice="it4") +``` + +The module uses the MBROLA command line tool under the hood. Ensure MBROLA is installed and available in your system path, or WSL if on Windows. + + +## Troubleshooting + +- Ensure MBROLA and the required voices are installed and available at `/usr/share/mbrola//`. +- If you encounter an error about platform support, make sure you are running on Linux or WSL. +- Write an [issue](https://github.com/NeuroDevCo/pymbrola/issues), I'll look into it ASAP. + +## License + +`pymbrola` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license. diff --git a/src/mbrola.egg-info/SOURCES.txt b/src/mbrola.egg-info/SOURCES.txt new file mode 100644 index 0000000..eec0368 --- /dev/null +++ b/src/mbrola.egg-info/SOURCES.txt @@ -0,0 +1,13 @@ +LICENSE +README.md +pyproject.toml +src/__about___.py +src/__init__.py +src/mbrola.py +src/mbrola.egg-info/PKG-INFO +src/mbrola.egg-info/SOURCES.txt +src/mbrola.egg-info/dependency_links.txt +src/mbrola.egg-info/requires.txt +src/mbrola.egg-info/top_level.txt +tests/test_mbrola.py +tests/test_validations.py \ No newline at end of file diff --git a/src/mbrola.egg-info/dependency_links.txt b/src/mbrola.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/mbrola.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/src/mbrola.egg-info/requires.txt b/src/mbrola.egg-info/requires.txt new file mode 100644 index 0000000..ccaadb0 --- /dev/null +++ b/src/mbrola.egg-info/requires.txt @@ -0,0 +1 @@ +pytest>=8.3.5 diff --git a/src/mbrola.egg-info/top_level.txt b/src/mbrola.egg-info/top_level.txt new file mode 100644 index 0000000..96f5530 --- /dev/null +++ b/src/mbrola.egg-info/top_level.txt @@ -0,0 +1,3 @@ +__about___ +__init__ +mbrola diff --git a/mbrola/mbrola.py b/src/mbrola.py similarity index 100% rename from mbrola/mbrola.py rename to src/mbrola.py diff --git a/tests/test_mbrola.py b/tests/test_mbrola.py index f421dcd..469db0a 100644 --- a/tests/test_mbrola.py +++ b/tests/test_mbrola.py @@ -3,7 +3,7 @@ import os from pathlib import Path import pytest -from mbrola import mbrola +import mbrola cafe = mbrola.MBROLA("cafè", ["k", "a", "f", "f", "E1"], 100, 200, (1, 1)) diff --git a/tests/test_validations.py b/tests/test_validations.py index 9a364bc..1d49874 100644 --- a/tests/test_validations.py +++ b/tests/test_validations.py @@ -1,7 +1,7 @@ """Test validation functions.""" import pytest -from mbrola import mbrola +import mbrola WORD = "mbrola" PHON = list(WORD) diff --git a/uv.lock b/uv.lock index c8238b3..b7b8979 100644 --- a/uv.lock +++ b/uv.lock @@ -342,7 +342,7 @@ wheels = [ [[package]] name = "mbrola" -version = "0.2.0" +version = "0.2.1" source = { editable = "." } dependencies = [ { name = "pytest" },