Skip to content

Commit

Permalink
feat: Refactor audio processing and build system
Browse files Browse the repository at this point in the history
- **Deprecate pysamplerate**: Removed usage of pysamplerate module and integrated libsamplerate directly.
- **Add CMake support**: Introduced CMake for better build management.
- **Update .gitignore**: Expanded to include various build and environment files.
- **Refactor setup.py**: Enhanced setup script to support CMake and other improvements.
- **Remove deprecated files**: Deleted obsolete audio utility and extras modules.
- **Add new modules**: Introduced new core, audiosys, rateshift, and utils modules.
- **Update existing modules**: Modified stream and sync modules for compatibility with new changes.
  • Loading branch information
mrzahaki committed Aug 27, 2024
1 parent 4c3458b commit 098fde2
Show file tree
Hide file tree
Showing 39 changed files with 881 additions and 114 deletions.
87 changes: 79 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,14 +1,85 @@

/*
**/__pycache__/*
sudio/*.jpg
lab
dist

!examples
!.gitignore
!setup.py
!sudio
!README.md

!img

# Byte-compiled / optimized / DLL files
**/__pycache__/*
*.py[cod]
*$py.class

# C extensions
*.so
*.pyd

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# Environment directories
.env
.venv
env/
venv/
ENV/

# IDE specific files
.vscode/
.idea/

# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

sudio/rateshift/external/**/*
# But don't ignore CMakeLists.txt files
!sudio/rateshift/external/**/CMakeLists.txt
# Don't ignore the external directory itself
!sudio/rateshift/external/
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 3.15)
project(sudio)

add_subdirectory(sudio/rateshift)
19 changes: 19 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
include LICENSE
include README.md
include setup.py
include pyproject.toml
include MANIFEST.in
include CMakeLists.txt

recursive-include sudio *.py
recursive-include sudio *.hpp
recursive-include sudio *.cpp
recursive-include sudio *.txt
recursive-include sudio/rateshift/external *

recursive-include tests *.py

global-exclude *.pyc
global-exclude __pycache__
global-exclude *.so
global-exclude *.pyd
24 changes: 24 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[build-system]
requires = ["setuptools>=61.0", "setuptools_scm[toml]>=6.2", "wheel", "cmake>=3.18"]
build-backend = "setuptools.build_meta"

[project]
name = "sudio"
dynamic = ["version"]
description = "Audio Processing Platform"
authors = [{name = "mrzahaki"}]
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: Apache Software License"
]
dependencies = [
"scipy>=1.9.1",
"numpy>=1.23.3",
"pyaudio>=0.2.12",
"miniaudio>=1.52",
]
readme = "README.md"
requires-python = ">=3.7"
license = {text = "Apache License 2.0"}
[tool.setuptools_scm]
write_to = "sudio/_version.py"
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
scipy>=1.9.1
numpy>=1.23.3
pyaudio>=0.2.12
miniaudio>=1.52
143 changes: 117 additions & 26 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,129 @@
import setuptools
import os
import subprocess
import sys
from pathlib import Path

with open("README.md", "r") as fh:
long_description = fh.read()
from setuptools import setup, find_packages, Extension
from setuptools.command.build_ext import build_ext

# CMake platform mapping
CMAKE_PLATFORMS = {
"win32": "Win32",
"win-amd64": "x64",
"win-arm32": "ARM",
"win-arm64": "ARM64",
}

setuptools.setup(
class CMakeExtension(Extension):
def __init__(self, name: str, sourcedir: str = "") -> None:
super().__init__(name, sources=[])
self.sourcedir = os.fspath(Path(sourcedir).resolve())

class CMakeBuild(build_ext):
def build_extension(self, ext: CMakeExtension) -> None:
ext_fullpath = Path.cwd() / self.get_ext_fullpath(ext.name)
extdir = ext_fullpath.parent.resolve()

debug = int(os.environ.get("DEBUG", 0)) if self.debug is None else self.debug
cfg = "Debug" if debug else "Release"

cmake_generator = os.environ.get("CMAKE_GENERATOR", "")

cmake_args = [
f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={extdir}{os.sep}",
f"-DPYTHON_EXECUTABLE={sys.executable}",
f"-DCMAKE_BUILD_TYPE={cfg}",
f"-DPACKAGE_VERSION_INFO={self.distribution.get_version()}",
]
build_args = []

if "CMAKE_ARGS" in os.environ:
cmake_args += [item for item in os.environ["CMAKE_ARGS"].split(" ") if item]

if self.compiler.compiler_type != "msvc":
self._setup_unix_build(cmake_generator, cmake_args)
else:
self._setup_windows_build(cmake_generator, cmake_args, build_args, cfg, extdir)

self._setup_cross_platform_args(build_args)

build_temp = Path(self.build_temp) / ext.name
build_temp.mkdir(parents=True, exist_ok=True)

self._run_cmake_build(ext, cmake_args, build_args, build_temp)

def _setup_unix_build(self, cmake_generator, cmake_args):
if not cmake_generator or cmake_generator == "Ninja":
try:
import ninja
ninja_executable_path = Path(ninja.BIN_DIR) / "ninja"
cmake_args.extend([
"-GNinja",
f"-DCMAKE_MAKE_PROGRAM:FILEPATH={ninja_executable_path}",
])
except ImportError:
pass

def _setup_windows_build(self, cmake_generator, cmake_args, build_args, cfg, extdir):
single_config = any(x in cmake_generator for x in {"NMake", "Ninja"})
contains_arch = any(x in cmake_generator for x in {"ARM", "Win64"})

if not single_config and not contains_arch:
cmake_args.append(f"-A{CMAKE_PLATFORMS[self.plat_name]}")

if not single_config:
cmake_args.append(f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{cfg.upper()}={extdir}")
build_args.extend(["--config", cfg])

def _setup_cross_platform_args(self, build_args):
if "universal2" in self.plat_name:
cmake_args.append("-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64")

if self.plat_name.startswith("macosx-") and "MACOSX_DEPLOYMENT_TARGET" not in os.environ:
os.environ["MACOSX_DEPLOYMENT_TARGET"] = self.plat_name.split("-")[1]

if "CMAKE_BUILD_PARALLEL_LEVEL" not in os.environ:
if hasattr(self, "parallel") and self.parallel:
build_args.append(f"-j{self.parallel}")

def _run_cmake_build(self, ext, cmake_args, build_args, build_temp):
subprocess.run(
["cmake", ext.sourcedir, *cmake_args], cwd=build_temp, check=True
)
subprocess.run(
["cmake", "--build", ".", *build_args], cwd=build_temp, check=True
)

def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()

setup(
name='sudio',
version='1.0.9.343',
packages=[
'sudio',
'sudio.extras',
'sudio.wrap',
'sudio.stream',
'sudio.types',
'sudio.audioutils',
'sudio.metadata'
],
version='1.0.9.35',
author="mrzahaki",
author_email="mrzahaki@gmail.com",
description="Audio Processing Platform",
long_description=long_description,
install_requires=[
'scipy>=1.9.1',
'numpy>=1.23.3',
'pyaudio>=0.2.12',
'miniaudio>=1.52',
'samplerate>=0.1.0',
],
long_description=read('README.md'),
long_description_content_type="text/markdown",
url="https://github.com/MrZahaki/sudio",
license='Apache License 2.0',
packages=find_packages(),
package_dir={'': '.'},
ext_modules=[CMakeExtension('sudio.rateshift')],
cmdclass={'build_ext': CMakeBuild},
classifiers=[
"Programming Language :: Python :: 3",
'License :: OSI Approved :: Apache Software License',
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
],
python_requires='>=3.7',
license='Apache License 2.0',
license_files=['LICENSE'],
)
zip_safe=False,
)
4 changes: 2 additions & 2 deletions sudio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
Software license: "Apache License 2.0". See https://choosealicense.com/licenses/apache-2.0/
"""
from sudio.pipeline import Pipeline
from sudio._master import Master
import sudio.types
from sudio.core import Master
import sudio.types
3 changes: 3 additions & 0 deletions sudio/audiosys/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@


from sudio.audiosys.miniaudio import _lib
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions sudio/audioutils/codec.py → sudio/audiosys/codec.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from _miniaudio import ffi, lib

from sudio.types import LibSampleFormat, DitherMode, DecodeError
from sudio.audioutils.typeconversion import get_sample_width_from_format
from sudio.extras.io import get_encoded_filename_bytes
from sudio.audiosys.typeconversion import get_sample_width_from_format
from sudio.utils.io import get_encoded_filename_bytes



Expand Down
6 changes: 3 additions & 3 deletions sudio/audioutils/codecinfo.py → sudio/audiosys/codecinfo.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import os
from _miniaudio import ffi, lib

from sudio.audioutils.fileinfo import AudioFileInfo
from sudio.audiosys.fileinfo import AudioFileInfo
from sudio.types import FileFormat, LibSampleFormat, DecodeError
from sudio.extras.io import get_encoded_filename_bytes
from sudio.audioutils.typeconversion import get_format_from_width
from sudio.utils.io import get_encoded_filename_bytes
from sudio.audiosys.typeconversion import get_format_from_width


def get_file_info(filename: str) -> AudioFileInfo:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from _miniaudio import ffi, lib
from sudio.audioutils.typeconversion import get_sample_width_from_format
from sudio.audiosys.typeconversion import get_sample_width_from_format
from sudio.types import LibSampleFormat, FileFormat

class AudioFileInfo:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from sudio.audioutils.audio import Audio
from sudio.audiosys.audio import Audio

def get_default_input_device_info():
"""
Expand Down
File renamed without changes.
File renamed without changes.
15 changes: 6 additions & 9 deletions sudio/audioutils/sync.py → sudio/audiosys/sync.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import numpy as np
import samplerate

from sudio.rateshift import rateshift
from sudio.types import SampleFormat
from sudio.audioutils.audio import Audio
from sudio.audioutils.channel import shuffle2d_channels
from sudio.audiosys.audio import Audio
from sudio.audiosys.channel import shuffle2d_channels


def synchronize_audio(rec,
Expand Down Expand Up @@ -62,17 +61,15 @@ def synchronize_audio(rec,
if not sample_rate == rec['frameRate']:
scale = sample_rate / rec['frameRate']

# firwin = scisig.firwin(23, fc)
# firdn = lambda firwin, data, scale: samplerate.resample(data, )
if len(data.shape) == 1:
# mono
data = samplerate.resample(data, scale, converter_type='sinc_fastest')
data = rateshift.resample(data, scale, rateshift.ConverterType.sinc_fastest, 1)
else:
# multi channel
res = samplerate.resample(data[0], scale, converter_type='sinc_fastest')
res = rateshift.resample(data[0], scale, rateshift.ConverterType.sinc_fastest, 1)
for i in data[1:]:
res = np.vstack((res,
samplerate.resample(i, scale, converter_type='sinc_fastest')))
rateshift.resample(i, scale, rateshift.ConverterType.sinc_fastest, 1)))
data = res

if output_data.startswith('b') and rec['nchannels'] > 1:
Expand Down
File renamed without changes.
Loading

0 comments on commit 098fde2

Please sign in to comment.