Python bindings for libllsm2 (import name: pyllsm2)
Project description
pyllsm2
pyllsm2 is a Python wrapper for libllsm2, focused on a clear,
NumPy-friendly API for speech analysis and synthesis.
The package now has two explicit API layers:
- Python-first API at
pyllsm2 - Raw CFFI API at
pyllsm2.raw
Most users should start with pyllsm2.
Additional Documentation
Detailed repository structure and API documentation are available in:
docs/README.zh-CN.mddocs/project-structure.zh-CN.mddocs/api-python.zh-CN.mddocs/api-raw.zh-CN.mddocs/development.zh-CN.md
Python Compatibility Layer
To improve NumPy integration and reduce Python-side loops, this package adds:
src/pyllsm2/python_compat.c
This file exists only for Python-side integration helpers that bind high-level
feature containers to C-backed memory layouts. It is not part of upstream
libllsm2 core sources.
C Source Modifications
This repository intentionally modifies a small part of the bundled C sources to support direct NumPy-style memory sharing for high-level feature arrays.
Modified files:
src/pyllsm2/python_compat.cvendor/libllsm2/llsm.hvendor/libllsm2/container.cvendor/libllsm2/frame.c
Purpose of these modifications:
- make
Layer0Featuresharmonic arrays C-backed and directly viewable as NumPy arrays - make
Layer1Featuresscalar/vector arrays C-backed and directly viewable as NumPy arrays - remove reliance on Python-side auto-commit array wrappers for common ndarray workflows
- remove high-level legacy getter/setter style feature access in favor of direct ndarray properties
- keep chunk copy/free logic consistent when frame members are rebound to shared array storage
In the modified C/C header files, comments marked with pyllsm2 modification
identify the added compatibility code paths.
Internal audit note for src/pyllsm2/python_compat.c:
- retired legacy helper exports that only served the pre-ndarray compat path
- kept only helpers still used by the current high-level wrapper or raw regression tests
- canonicalized F0 / Rd / harmonic writes through shared ndarray-backed buffers
- stopped relying on the old
llsm_py_chunk_resample_linear_f0path because it no longer matches the post-refactor chunk ownership model
Scope
- Wraps the public
libllsm2APIs from:llsm.hdsputils.hllsmrt.hllsmutils.h
- Exposes selected
cigletAPIs used with LLSM2:qifftspec2envlfmodel_*ifdetector_*filterbank_*
pyin and gvps are intentionally not included in this package build.
Install
Editable install:
pip install -e ./pyllsm2
If your environment cannot create an isolated build environment:
pip install -e ./pyllsm2 --no-build-isolation
Build note: package build requires a libllsm2 source tree at one of:
vendor/libllsm2libllsm2../libllsm2
Quick Start
import pyllsm2
analysis_options = pyllsm2.AnalysisOptions()
analysis_options.thop = 128 / 16000.0
analysis_options.maxnhar = 120
analysis_options.maxnhar_e = 5
analysis_options.npsd = 128
synthesis_options = pyllsm2.SynthesisOptions(16000)
# f0 should come from an external F0 extractor such as librosa or parselmouth
layer0 = pyllsm2.analyze(analysis_options, x, 16000, f0)
layer1 = pyllsm2.to_layer1(layer0, 1024)
output = pyllsm2.synthesize(synthesis_options, layer1)
y = output.y
Analysis Flow
The Python-first workflow is intentionally split into two feature containers:
Layer0Features: harmonic-plus-noise features produced directly by analysisLayer1Features: source-filter style features derived from layer 0
Typical flow:
import pyllsm2
layer0 = pyllsm2.analyze(analysis_options, x, fs, f0)
layer1 = pyllsm2.to_layer1(layer0, 1024)
resynth0 = pyllsm2.synthesize(synthesis_options, layer0)
resynth1 = pyllsm2.synthesize(synthesis_options, layer1)
Python-First API
The top-level pyllsm2 module is intentionally small and discoverable.
Core classes
AnalysisOptionsSynthesisOptionsLayer0FeaturesLayer1FeaturesChunkCoderRTSynthBufferOutput
Core functions
analyze(...)to_layer1(...)to_layer0(...)synthesize(...)analyze_chunk(...)synthesize_output(...)warp_frequency(...)spectral_mean(...)spectrum_from_envelope(...)harmonic_analysis(...)synthesize_harmonic_frame(...)qifft(...)spec2env(...)lfmodel_from_rd(...)lfmodel_spectrum(...)lfmodel_period(...)ifdetector_estimate(...)
Layer-0 container
Layer0Features is the main analysis result. Common operations include:
layer0.f0layer0.ampllayer0.phselayer0.nharnp.log(layer0.ampl + 1e-6)layer0.ampl = np.zeros((nfrm, max_nhar), dtype=np.float32)layer0.phasepropagate(...)layer0.phasesync_rps(...)layer0.resample_linear_f0(...)layer0.to_layer1(...)
Array shapes and axis meanings:
layer0.f0: shape(nfrm,); axis 0 is frame index over timelayer0.nhar: shape(nfrm,); axis 0 is frame index over timelayer0.ampl: shape(nfrm, max_nhar); axis 1 is harmonic indexlayer0.phse: shape(nfrm, max_nhar); axis 1 is harmonic index
Layer-1 container
Layer1Features is the derived source-filter representation. Common operations include:
layer1.f0layer1.rdlayer1.vtmagnlayer1.vsphselayer1.vsphse_lengthsnp.mean(layer1.vtmagn, axis=0)layer1.vsphse = np.zeros((nfrm, max_nhar), dtype=np.float32)layer1.pitch_shift(...)layer1.to_layer0()
Array shapes and axis meanings:
layer1.f0: shape(nfrm,); axis 0 is frame index over timelayer1.rd: shape(nfrm,); axis 0 is frame index over timelayer1.vtmagn: shape(nfrm, nspec); axis 1 is spectral-bin indexlayer1.vsphse: shape(nfrm, max_nhar); axis 1 is source-harmonic indexlayer1.vsphse_lengths: shape(nfrm,); axis 0 is frame index over time
Advanced chunk API
Chunk remains available for advanced or low-level workflows, but it is no longer
the primary user-facing feature container.
Direct object-style usage is supported in normal workflows. Context-manager usage is also available when you want explicit resource cleanup.
When you do need Chunk, prefer layer-specific allocation and direct ndarray
properties instead of mixed member-style access:
Chunk.allocate_layer0(nfrm, fs=..., max_nhar=...)Chunk.allocate_layer1(nfrm, fs=..., nspec=..., max_nhar=...)chunk.f0,chunk.ampl,chunk.phse,chunk.nharchunk.rd,chunk.vtmagn,chunk.vsphse,chunk.vsphse_lengths
Raw API
Low-level access is available under pyllsm2.raw.
Use this layer only if you need direct CFFI access to native pointers, raw
constants, or one-to-one mappings of libllsm2 symbols.
import pyllsm2
ffi = pyllsm2.raw.ffi
lib = pyllsm2.raw.lib
opt = lib.llsm_create_aoptions()
method = pyllsm2.raw.LLSM_AOPTION_HMPP
Examples of what lives under pyllsm2.raw:
ffilibLLSM_*constantsllsm_*native symbolscontainer_attach(...)- pointer-copy helpers such as
copy_fp_ptr(...)
Design Notes
- Top-level exports are Python-first and intentionally avoid raw symbol spam.
- Top-level analysis flow is centered on
Layer0Features -> Layer1Features. - Legacy aliases such as
AOptions,SOptions,analyze_frames, andsynthesize_audioare no longer part of the public top-level API. - Raw
libllsm2access remains available, but is now clearly separated underpyllsm2.raw.
Tests
Tests are now grouped by intent inside tests/:
tests/unit/: lightweight unit tests for high-level ndarray-oriented APIs.tests/learning/: practical, example-like tests that replace the oldexamples/folder.tests/raw/: focused tests forpyllsm2.rawhelpers, constants, pointers, and interop.tests/integration/: functional/integration coverage, including ports oflibllsm2/test/*.
Generated audio from the learning and integration suites is written to tests/audio_outputs/.
Install test dependencies:
pip install -e ./pyllsm2[test] --no-build-isolation
Run tests:
pytest tests -q
Packaging
pyllsm2 uses:
pyproject.tomlsetuptoolscffisrc/layout
License
pyllsm2 is licensed under GPL-3.0-or-later.
- Main license text:
LICENSE - Third-party notices:
THIRD_PARTY_NOTICES.md
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file pyllsm2-0.2.0.tar.gz.
File metadata
- Download URL: pyllsm2-0.2.0.tar.gz
- Upload date:
- Size: 158.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37ad7b647ca5759c98ce67b8494038062c733839dd7e2fce7d7ca03c6fa2fce5
|
|
| MD5 |
582e1260fcb36da675ccb074d7b07de3
|
|
| BLAKE2b-256 |
a61797059e7bbe63a5673315a795b523c48af9f31d367e940babe0011eccb74a
|
Provenance
The following attestation bundles were made for pyllsm2-0.2.0.tar.gz:
Publisher:
publish-pypi.yml on yjzxkxdn/Python-Wrapper-for-Llsm2-Vocoder
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyllsm2-0.2.0.tar.gz -
Subject digest:
37ad7b647ca5759c98ce67b8494038062c733839dd7e2fce7d7ca03c6fa2fce5 - Sigstore transparency entry: 1066542264
- Sigstore integration time:
-
Permalink:
yjzxkxdn/Python-Wrapper-for-Llsm2-Vocoder@63b17e6b333ab94f0547783dbd69ae32cf9a813f -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/yjzxkxdn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@63b17e6b333ab94f0547783dbd69ae32cf9a813f -
Trigger Event:
push
-
Statement type: