Skip to content

Commit

Permalink
Add __libsoxr_version__ to check version of linked libsoxr (#20)
Browse files Browse the repository at this point in the history
* Get __libsoxr_version__ from separated C source
  • Loading branch information
dofuuz authored Aug 15, 2023
1 parent 65b743a commit 04b0430
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 20 deletions.
39 changes: 38 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
src/soxr/_csoxr_version.c
src/soxr/_version.py


### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down Expand Up @@ -94,7 +99,22 @@ ipython_config.py
# install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
Expand Down Expand Up @@ -136,3 +156,20 @@ dmypy.json

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

### Python Patch ###
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
poetry.toml

# ruff
.ruff_cache/

# LSP config files
pyrightconfig.json
9 changes: 8 additions & 1 deletion BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,18 @@ python -m build
libsoxr should be installed before building.
(e.g. `sudo apt install libsoxr-dev`)
```
python -m build -C=--global-option=--use-system-libsoxr
python -m build -C--build-option=--use-system-libsoxr
```
It will link libsoxr dynamically and libsoxr won't bundled in the wheel package.


## Install
Install built .whl package(not .tar.gz sdist).
```
pip install dist/soxr-[...].whl
```


## Test
```
# Install dependencies
Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ include libsoxr/src/*.c
include libsoxr/src/*.h
include libsoxr/COPYING.LGPL
include libsoxr/LICENCE
include src/soxr/csoxr_version.c
include src/soxr/*.h
include src/soxr/*.pxd
include src/soxr/*.py
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ requires = [
"setuptools>=42",
"wheel",
"Cython>=3.0a7",
"setuptools_scm[toml]>=3.4",
"setuptools_scm[toml]>=6.2",
"oldest-supported-numpy"
]
build-backend = "setuptools.build_meta"

[tool.setuptools_scm]
write_to = "src/soxr/version.py"
write_to = "src/soxr/_version.py"
63 changes: 55 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
"""
Python-SoXR setup.py for Cython build
Please refer to BUILDING.md for building instructions.
Do not run setup.py directly for the build process.
"""

import logging
import subprocess
import sys
import sysconfig

from setuptools import setup, Extension

from distutils.ccompiler import get_default_compiler
from setuptools import setup, Extension
from setuptools.command.sdist import sdist


SYS_LIBSOXR = False

# python -m build -C=--global-option=--use-system-libsoxr
# python -m build -C=--build-option=--use-system-libsoxr
if '--use-system-libsoxr' in sys.argv:
sys.argv.remove('--use-system-libsoxr')
SYS_LIBSOXR = True
Expand All @@ -28,7 +37,37 @@ def include_dirs(self):
def include_dirs(self, dirs):
self._include = dirs

src_libsoxr = [

def get_git_version(cwd=''):
try:
result = subprocess.run(
['git', 'describe', '--tags', '--always', '--dirty'],
cwd=cwd, capture_output=True, check=True, text=True)

ver = result.stdout.strip()
return ver
except Exception as e:
logging.warning(f'Error retrieving submodule version: {e}')
return 'unknown'


CSOXR_VERSION_C = '''
#include "csoxr_version.h"
const char * libsoxr_version() { return "%s"; }
'''


class SDistBundledCommand(sdist):
def run(self):
ver = get_git_version('libsoxr')
with open(f'src/soxr/_csoxr_version.c', 'wt') as f:
f.write(CSOXR_VERSION_C % (ver))
logging.info(f'libsoxr version: {ver}')

super().run()


src_static = [
'libsoxr/src/soxr.c',
'libsoxr/src/data-io.c',
'libsoxr/src/dbesi0.c',
Expand All @@ -55,11 +94,16 @@ def include_dirs(self, dirs):
# 'libsoxr/src/cr64s.c',
# 'libsoxr/src/pffft64s.c',
# 'libsoxr/src/util64s.c',

# Cython wrapper
'src/soxr/cysoxr.pyx',
'src/soxr/_csoxr_version.c', # csoxr libsoxr_version()
]

src = [
src_dynamic = [
# Cython wrapper
'src/soxr/cysoxr.pyx'
'src/soxr/cysoxr.pyx',
'src/soxr/csoxr_version.c', # libsoxr soxr_version()
]

compile_args = ['-DSOXR_LIB']
Expand All @@ -76,25 +120,28 @@ def include_dirs(self, dirs):
extensions = [
CySoxrExtension(
"soxr.cysoxr",
src_libsoxr + src,
src_static,
include_dirs=['libsoxr/src', 'src/soxr'],
language="c",
extra_compile_args=compile_args)
]

extensions_dynamic = [
CySoxrExtension('soxr.cysoxr', src, language='c', libraries=['soxr'])
CySoxrExtension('soxr.cysoxr', src_dynamic, language='c', libraries=['soxr'])
]


if __name__ == "__main__":
from Cython.Build import cythonize

if SYS_LIBSOXR:
logging.info('Building Python-SoXR using system libsoxr...')
setup(
ext_modules=cythonize(extensions_dynamic, language_level='3'),
)
else:
logging.info('Building Python-SoXR using bundled libsoxr...')
setup(
cmdclass={'sdist': SDistBundledCommand},
ext_modules=cythonize(extensions, language_level='3'),
)
15 changes: 7 additions & 8 deletions src/soxr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@

import numpy as np

from .cysoxr import CySoxr
from .cysoxr import cysoxr_divide_proc
from .cysoxr import cysoxr_oneshot
from . import cysoxr
from .cysoxr import QQ, LQ, MQ, HQ, VHQ
from ._version import __version__

from .version import version as __version__

__libsoxr_version__ = cysoxr.libsoxr_version()

# libsoxr locates memory per each channel.
# Too much channels will cause memory error.
Expand Down Expand Up @@ -83,7 +82,7 @@ def __init__(self,

q = _quality_to_enum(quality)

self._cysoxr = CySoxr(in_rate, out_rate, num_channels, self._type.type, q)
self._cysoxr = cysoxr.CySoxr(in_rate, out_rate, num_channels, self._type.type, q)

def resample_chunk(self, x, last=False):
""" Resample chunk with streaming resampler
Expand Down Expand Up @@ -157,14 +156,14 @@ def resample(x, in_rate: float, out_rate: float, quality='HQ'):
x = np.ascontiguousarray(x) # make array C-contiguous

if x.ndim == 1:
y = cysoxr_divide_proc(in_rate, out_rate, x[:, np.newaxis], q)
y = cysoxr.cysoxr_divide_proc(in_rate, out_rate, x[:, np.newaxis], q)
return np.squeeze(y, axis=1)
elif x.ndim == 2:
num_channels = x.shape[1]
if num_channels < 1 or _CH_LIMIT < num_channels:
raise ValueError(_CH_EXEED_ERR_STR.format(num_channels))

return cysoxr_divide_proc(in_rate, out_rate, x, q)
return cysoxr.cysoxr_divide_proc(in_rate, out_rate, x, q)
else:
raise ValueError('Input must be 1-D or 2-D array')

Expand All @@ -175,4 +174,4 @@ def _resample_oneshot(x, in_rate: float, out_rate: float, quality='HQ'):
`soxr_oneshot()` becomes slow with long input.
This function exists for test purpose.
"""
return cysoxr_oneshot(in_rate, out_rate, x, _quality_to_enum(quality))
return cysoxr.cysoxr_oneshot(in_rate, out_rate, x, _quality_to_enum(quality))
5 changes: 5 additions & 0 deletions src/soxr/_csoxr_version.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include "csoxr_version.h"

const char * libsoxr_version() {
return "undefined";
}
4 changes: 4 additions & 0 deletions src/soxr/csoxr.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,7 @@ cdef extern from 'soxr.h':
cdef unsigned long SOXR_VHQ

cdef soxr_io_spec_t soxr_io_spec(soxr_datatype_t itype, soxr_datatype_t otype)


cdef extern from 'csoxr_version.h':
cdef const char * libsoxr_version()
6 changes: 6 additions & 0 deletions src/soxr/csoxr_version.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <soxr.h>
#include "csoxr_version.h"

const char * libsoxr_version() {
return soxr_version();
}
1 change: 1 addition & 0 deletions src/soxr/csoxr_version.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const char * libsoxr_version();
4 changes: 4 additions & 0 deletions src/soxr/cysoxr.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ ctypedef fused datatype_t:
cython.short


cpdef str libsoxr_version():
return csoxr.libsoxr_version().decode('UTF-8')


# NumPy scalar type to soxr_io_spec_t
cdef csoxr.soxr_io_spec_t to_io_spec(type ntype):
cdef csoxr.soxr_datatype_t io_type
Expand Down

0 comments on commit 04b0430

Please sign in to comment.