[![PyPI](https://img.shields.io/pypi/v/pya.svg)](https://pypi.org/project/pya)
[![License](https://img.shields.io/github/license/interactive-sonification/pya.svg)](LICENSE)
# pya
|Branch|`master`|`develop`|
|------:|--------:|---------:|
|[CI-Linux/MacOS](https://github.com/interactive-sonification/pya/actions/workflows/pya-ci.yaml) | [![Build Status Master](https://github.com/interactive-sonification/pya/actions/workflows/pya-ci.yaml/badge.svg?branch=master)](https://github.com/interactive-sonification/pya/actions/workflows/pya-ci.yaml?query=branch%3Amaster) | [![Build Status Develop](https://github.com/interactive-sonification/pya/actions/workflows/pya-ci.yaml/badge.svg?branch=develop)](https://github.com/interactive-sonification/pya/actions/workflows/pya-ci.yaml?query=branch%3Adevelop) |
|[CI-Windows](https://ci.appveyor.com/project/aleneum/pya-b7gkx/)| ![Build status AppVeyor](https://ci.appveyor.com/api/projects/status/vn61qeri0uyxeedv/branch/master?svg=true) | ![Build status AppVeyor](https://ci.appveyor.com/api/projects/status/vn61qeri0uyxeedv/branch/develop?svg=true) |
|Changes|[![GitHub commits](https://img.shields.io/github/commits-since/interactive-sonification/pya/v0.5.0/master.svg)](https://github.com/interactive-sonification/pya/compare/v0.5.0...master) | [![GitHub commits](https://img.shields.io/github/commits-since/interactive-sonification/pya/v0.5.0/develop.svg)](https://github.com/interactive-sonification/pya/compare/v0.5.0...develop) |
|Binder|[![Master Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/interactive-sonification/pya/master?filepath=examples%2Fpya-examples.ipynb) | [![Develop Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/interactive-sonification/pya/develop?filepath=examples%2Fpya-examples.ipynb) |
## What is pya?
pya is a package to support creation and manipulation of audio signals with Python.
It uses numpy arrays to store and compute audio signals.
* Documentation: see examples/pya-examples.ipynb for a quick tutorial and [Documentation](https://interactive-sonification.github.io/pya/index.html)
* Source code: https://github.com/interactive-sonification/pya
It provides:
* Asig - a versatile audio signal class
* Ugen - a subclass of Asig, which offers unit generators
such as sine, square, sawtooth, noise
* Aserver - an audio server class for queuing and playing Asigs
* Arecorder - an audio recorder class
* Aspec - an audio spectrum class, using rfft as real-valued signals are always implied
* Astft - an audio STFT (short-term Fourier transform) class
* A number of helper functions, e.g. device_info()
pya can be used for
* multi-channel audio processing
* auditory display and sonification
* sound synthesis experiment
* audio applications in general such as games or GUI-enhancements
* signal analysis and plotting
At this time pya is more suitable for offline rendering than realtime.
## Authors and Contributors
* [Thomas](https://github.com/thomas-hermann) (author, maintainer)
* [Jiajun](https://github.com/wiccy46) (co-author, maintainer)
* [Alexander](https://github.com/aleneum) (maintainer)
* Contributors will be acknowledged here, contributions are welcome.
## Installation
Install using
```
pip install pya
```
However to play and record audio you need a backend.
- `pip install pya[remote]` for a web based Jupyter backend
- `pip install pya[pyaudio]` for `portaudio` and its Python wrapper `PyAudio`
### Using Conda
Pyaudio can be installed via [conda](https://docs.conda.io):
```
conda install pyaudio
```
Disclaimer: Python 3.10+ requires PyAudio 0.2.12 which is not available on Conda as of December 2022. [Conda-forge](https://conda-forge.org/) provides a version only for Linux at the moment. Users of Python 3.10 should for now use other installation options.
### Using Homebrew and PIP (MacOS only)
```
brew install portaudio
```
Then
```
pip install pya
```
For Apple ARM Chip, if you failed to install the PyAudio dependency, you can follow this guide: [Installation on ARM chip](https://stackoverflow.com/a/73166852/4930109)
- Option 1: Create .pydistutils.cfg in your home directory, `~/.pydistutils.cfg`, add:
```
echo "[build_ext]
include_dirs=$(brew --prefix portaudio)/include/
library_dirs=$(brew --prefix portaudio)/lib/" > ~/.pydistutils.cfg
```
Use pip:
```
pip install pya
```
You can remove the `.pydistutils.cfg` file after installation.
- Option 2: Use `CFLAGS`:
```
CFLAGS="-I/opt/homebrew/include -L/opt/homebrew/lib" pip install pya
```
### Using PIP (Linux)
Try `sudo apt-get install portaudio19-dev` or equivalent to your distro, then
```
pip install pya
```
### Using PIP (Windows)
[PyPI](https://pypi.org/) provides [PyAudio wheels](https://pypi.org/project/PyAudio/#files) for Windows including portaudio:
```
pip install pyaudio
```
should be sufficient.
## A simple example
### Startup:
```Python
import pya
s = pya.Aserver(bs=1024)
pya.Aserver.default = s # to set as default server
s.boot()
```
### Create an Asig signal:
A 1s / 440 Hz sine tone at sampling rate 44100 as channel name 'left':
```Python
import numpy as np
signal_array = np.sin(2 * np.pi * 440 * np.linspace(0, 1, 44100))
atone = pya.Asig(signal_array, sr=44100, label='1s sine tone', cn=['left'])
```
Other ways of creating an Asig object:
```Python
asig_int = pya.Asig(44100, sr=44100) # zero array with 44100 samples
asig_float = pya.Asig(2., sr=44100) # float argument, 2 seconds of zero array
asig_str = pya.Asig('./song.wav') # load audio file
asig_ugen = pya.Ugen().square(freq=440, sr=44100, dur=2., amp=0.5) # using Ugen class to create common waveforms
```
Audio files are also possible using the file path. `WAV` should work without issues. `MP3` is supported but may raise error if [FFmpeg](https://ffmpeg.org/).
If you use Anaconda, installation is quite easy:
`conda install -c conda-forge ffmpeg`
Otherwise:
* Mac or Linux with brew
- `brew install ffmpeg`
* On Linux
- Install FFmpeg via apt-get: `sudo apt install ffmpeg`
* On Windows
- Download the latest distribution from https://ffmpeg.zeranoe.com/builds/
- Unzip the folder, preferably to `C:\`
- Append the FFmpeg binary folder (e.g. `C:\ffmpeg\bin`) to the PATH system variable ([How do I set or change the PATH system variable?](https://www.java.com/en/download/help/path.xml))
### Key attributes
* `atone.sig` --> The numpy array containing the signal is
* `atone.sr` --> the sampling rate
* `atone.cn` --> the list of custom defined channel names
* `atone.label` --> a custom set identifier string
### Play signals
atone.play(server=s)
play() uses Aserver.default if server is not specified
Instead of specifying a long standing server. You can also use `Aserver` as a context:
```Python
with pya.Aserver(sr=48000, bs=256, channels=2) as aserver:
atone.play(server=aserver) # Or do: aserver.play(atone)
```
The benefit of this is that it will handle server bootup and shutdown for you. But notice that server up/down introduces extra latency.
### Play signal on a specific device
```Python
from pya import find_device
from pya import Aserver
devices = find_device() # This will return a dictionary of all devices, with their index, name, channels.
s = Aserver(sr=48000, bs=256, device=devices['name_of_your_device']['index'])
```
### Plotting signals
to plot the first 1000 samples:
atone[:1000].plot()
to plot the magnitude and phase spectrum:
atone.plot_spectrum()
to plot the spectrum via the Aspec class
atone.to_spec().plot()
to plot the spectrogram via the Astft class
atone.to_stft().plot(ampdb)
### Selection of subsets
* Asigs support multi-channel audio (as columns of the signal array)
* `a1[:100, :3]` would select the first 100 samples and the first 3 channels,
* `a1[{1.2:2}, ['left']]` would select the channel named 'left' using a time slice from 1
### Recording from Device
`Arecorder` allows recording from input device
```Python
import time
from pya import find_device
from pya import Arecorder
devices = find_device() # Find the index of the input device
arecorder = Arecorder(device=some_index, sr=48000, bs=512) # Or not set device to let pya find the default device
arecorder.boot()
arecorder.record()
time.sleep(2) # Recording is non-blocking
arecorder.stop()
last_recording = arecorder.recordings[-1] # Each time a recorder stop, a new recording is appended to recordings
```
### Method chaining
Asig methods usually return an Asig, so methods can be chained, e.g
atone[{0:1.5}].fade_in(0.1).fade_out(0.8).gain(db=-6).plot(lw=0.1).play(rate=0.4, onset=1)
### Learning more
* Please check the examples/pya-examples.ipynb for more examples and details.
## Contributing
* Please get in touch with us if you wish to contribute. We are happy to be involved in the discussion of new features and to receive pull requests.
Raw data
{
"_id": null,
"home_page": "https://github.com/interactive-sonification/pya",
"name": "pya",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "sonification, sound synthesis",
"author": "Thomas Hermann",
"author_email": "thermann@techfak.uni-bielefeld.de",
"download_url": "https://files.pythonhosted.org/packages/48/c4/89870b682fed797296555bbd27c97b91c3fab2a9f7fc8991ceeec1b30a40/pya-0.5.2.tar.gz",
"platform": null,
"description": "[![PyPI](https://img.shields.io/pypi/v/pya.svg)](https://pypi.org/project/pya)\n[![License](https://img.shields.io/github/license/interactive-sonification/pya.svg)](LICENSE)\n\n# pya\n\n|Branch|`master`|`develop`|\n|------:|--------:|---------:|\n|[CI-Linux/MacOS](https://github.com/interactive-sonification/pya/actions/workflows/pya-ci.yaml) | [![Build Status Master](https://github.com/interactive-sonification/pya/actions/workflows/pya-ci.yaml/badge.svg?branch=master)](https://github.com/interactive-sonification/pya/actions/workflows/pya-ci.yaml?query=branch%3Amaster) | [![Build Status Develop](https://github.com/interactive-sonification/pya/actions/workflows/pya-ci.yaml/badge.svg?branch=develop)](https://github.com/interactive-sonification/pya/actions/workflows/pya-ci.yaml?query=branch%3Adevelop) |\n|[CI-Windows](https://ci.appveyor.com/project/aleneum/pya-b7gkx/)| ![Build status AppVeyor](https://ci.appveyor.com/api/projects/status/vn61qeri0uyxeedv/branch/master?svg=true) | ![Build status AppVeyor](https://ci.appveyor.com/api/projects/status/vn61qeri0uyxeedv/branch/develop?svg=true) | \n|Changes|[![GitHub commits](https://img.shields.io/github/commits-since/interactive-sonification/pya/v0.5.0/master.svg)](https://github.com/interactive-sonification/pya/compare/v0.5.0...master) | [![GitHub commits](https://img.shields.io/github/commits-since/interactive-sonification/pya/v0.5.0/develop.svg)](https://github.com/interactive-sonification/pya/compare/v0.5.0...develop) |\n|Binder|[![Master Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/interactive-sonification/pya/master?filepath=examples%2Fpya-examples.ipynb) | [![Develop Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/interactive-sonification/pya/develop?filepath=examples%2Fpya-examples.ipynb) |\n\n## What is pya?\n\npya is a package to support creation and manipulation of audio signals with Python.\nIt uses numpy arrays to store and compute audio signals.\n\n * Documentation: see examples/pya-examples.ipynb for a quick tutorial and [Documentation](https://interactive-sonification.github.io/pya/index.html)\n * Source code: https://github.com/interactive-sonification/pya\n\nIt provides:\n\n * Asig - a versatile audio signal class \n * Ugen - a subclass of Asig, which offers unit generators \n such as sine, square, sawtooth, noise\n * Aserver - an audio server class for queuing and playing Asigs\n * Arecorder - an audio recorder class\n * Aspec - an audio spectrum class, using rfft as real-valued signals are always implied\n * Astft - an audio STFT (short-term Fourier transform) class\n * A number of helper functions, e.g. device_info()\n\npya can be used for\n* multi-channel audio processing\n* auditory display and sonification\n* sound synthesis experiment\n* audio applications in general such as games or GUI-enhancements\n* signal analysis and plotting\n \nAt this time pya is more suitable for offline rendering than realtime.\n\n## Authors and Contributors\n\n* [Thomas](https://github.com/thomas-hermann) (author, maintainer)\n* [Jiajun](https://github.com/wiccy46) (co-author, maintainer)\n* [Alexander](https://github.com/aleneum) (maintainer)\n* Contributors will be acknowledged here, contributions are welcome.\n\n## Installation\n\nInstall using\n```\npip install pya\n```\n\nHowever to play and record audio you need a backend.\n\n- `pip install pya[remote]` for a web based Jupyter backend\n- `pip install pya[pyaudio]` for `portaudio` and its Python wrapper `PyAudio`\n\n### Using Conda\n\nPyaudio can be installed via [conda](https://docs.conda.io):\n\n```\nconda install pyaudio\n```\n\nDisclaimer: Python 3.10+ requires PyAudio 0.2.12 which is not available on Conda as of December 2022. [Conda-forge](https://conda-forge.org/) provides a version only for Linux at the moment. Users of Python 3.10 should for now use other installation options.\n\n### Using Homebrew and PIP (MacOS only)\n\n\n```\nbrew install portaudio\n```\n\nThen \n\n```\npip install pya\n```\n\nFor Apple ARM Chip, if you failed to install the PyAudio dependency, you can follow this guide: [Installation on ARM chip](https://stackoverflow.com/a/73166852/4930109)\n - Option 1: Create .pydistutils.cfg in your home directory, `~/.pydistutils.cfg`, add:\n\n ```\n echo \"[build_ext]\n include_dirs=$(brew --prefix portaudio)/include/\n library_dirs=$(brew --prefix portaudio)/lib/\" > ~/.pydistutils.cfg\n ```\n Use pip:\n\n ```\n pip install pya\n ```\n\n You can remove the `.pydistutils.cfg` file after installation.\n\n- Option 2: Use `CFLAGS`: \n\n ```\n CFLAGS=\"-I/opt/homebrew/include -L/opt/homebrew/lib\" pip install pya\n ```\n\n\n\n### Using PIP (Linux)\n\nTry `sudo apt-get install portaudio19-dev` or equivalent to your distro, then \n\n```\npip install pya\n```\n\n### Using PIP (Windows)\n\n[PyPI](https://pypi.org/) provides [PyAudio wheels](https://pypi.org/project/PyAudio/#files) for Windows including portaudio:\n\n```\npip install pyaudio\n```\n\nshould be sufficient.\n\n\n## A simple example\n\n### Startup:\n\n```Python\nimport pya\ns = pya.Aserver(bs=1024)\npya.Aserver.default = s # to set as default server\ns.boot()\n```\n\n### Create an Asig signal:\n\nA 1s / 440 Hz sine tone at sampling rate 44100 as channel name 'left':\n\n```Python\nimport numpy as np\nsignal_array = np.sin(2 * np.pi * 440 * np.linspace(0, 1, 44100))\natone = pya.Asig(signal_array, sr=44100, label='1s sine tone', cn=['left'])\n```\n\nOther ways of creating an Asig object:\n\n```Python\nasig_int = pya.Asig(44100, sr=44100) # zero array with 44100 samples\nasig_float = pya.Asig(2., sr=44100) # float argument, 2 seconds of zero array\nasig_str = pya.Asig('./song.wav') # load audio file\nasig_ugen = pya.Ugen().square(freq=440, sr=44100, dur=2., amp=0.5) # using Ugen class to create common waveforms\n```\n\nAudio files are also possible using the file path. `WAV` should work without issues. `MP3` is supported but may raise error if [FFmpeg](https://ffmpeg.org/).\n\nIf you use Anaconda, installation is quite easy:\n\n`conda install -c conda-forge ffmpeg`\n\nOtherwise:\n\n* Mac or Linux with brew\n - `brew install ffmpeg`\n* On Linux\n - Install FFmpeg via apt-get: `sudo apt install ffmpeg`\n* On Windows\n - Download the latest distribution from https://ffmpeg.zeranoe.com/builds/\n - Unzip the folder, preferably to `C:\\`\n - Append the FFmpeg binary folder (e.g. `C:\\ffmpeg\\bin`) to the PATH system variable ([How do I set or change the PATH system variable?](https://www.java.com/en/download/help/path.xml))\n### Key attributes\n* `atone.sig` --> The numpy array containing the signal is \n* `atone.sr` --> the sampling rate\n* `atone.cn` --> the list of custom defined channel names\n* `atone.label` --> a custom set identifier string\n\n### Play signals\n\n atone.play(server=s) \n\nplay() uses Aserver.default if server is not specified\n\nInstead of specifying a long standing server. You can also use `Aserver` as a context:\n\n```Python\nwith pya.Aserver(sr=48000, bs=256, channels=2) as aserver:\n atone.play(server=aserver) # Or do: aserver.play(atone)\n```\n\nThe benefit of this is that it will handle server bootup and shutdown for you. But notice that server up/down introduces extra latency.\n\n### Play signal on a specific device\n\n```Python\nfrom pya import find_device\nfrom pya import Aserver\ndevices = find_device() # This will return a dictionary of all devices, with their index, name, channels.\ns = Aserver(sr=48000, bs=256, device=devices['name_of_your_device']['index'])\n```\n\n\n### Plotting signals\n\nto plot the first 1000 samples:\n\n atone[:1000].plot()\n\nto plot the magnitude and phase spectrum:\n\n atone.plot_spectrum()\n\nto plot the spectrum via the Aspec class\n\n atone.to_spec().plot()\n\nto plot the spectrogram via the Astft class\n\n atone.to_stft().plot(ampdb)\n\n### Selection of subsets\n* Asigs support multi-channel audio (as columns of the signal array)\n * `a1[:100, :3]` would select the first 100 samples and the first 3 channels, \n * `a1[{1.2:2}, ['left']]` would select the channel named 'left' using a time slice from 1\n\n### Recording from Device\n\n`Arecorder` allows recording from input device \n\n```Python\nimport time\n\nfrom pya import find_device\nfrom pya import Arecorder\ndevices = find_device() # Find the index of the input device\narecorder = Arecorder(device=some_index, sr=48000, bs=512) # Or not set device to let pya find the default device \narecorder.boot()\narecorder.record()\ntime.sleep(2) # Recording is non-blocking\narecorder.stop()\nlast_recording = arecorder.recordings[-1] # Each time a recorder stop, a new recording is appended to recordings\n```\n\n### Method chaining\nAsig methods usually return an Asig, so methods can be chained, e.g\n\n atone[{0:1.5}].fade_in(0.1).fade_out(0.8).gain(db=-6).plot(lw=0.1).play(rate=0.4, onset=1)\n\n### Learning more\n* Please check the examples/pya-examples.ipynb for more examples and details.\n\n\n## Contributing \n* Please get in touch with us if you wish to contribute. We are happy to be involved in the discussion of new features and to receive pull requests.\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Python audio coding classes - for dsp and sonification",
"version": "0.5.2",
"project_urls": {
"Homepage": "https://github.com/interactive-sonification/pya"
},
"split_keywords": [
"sonification",
" sound synthesis"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "0e4934b5e96674e5e970e662cf63bc57d9a7e6c705d175511672db5b56e91aaf",
"md5": "10c2c998e2d2f3e340edb2c9e350b3f5",
"sha256": "c2288a84af8bd2850abe422a5b05e015475061ef4c0b0f217feadb0df296c691"
},
"downloads": -1,
"filename": "pya-0.5.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "10c2c998e2d2f3e340edb2c9e350b3f5",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 57640,
"upload_time": "2023-12-10T14:31:25",
"upload_time_iso_8601": "2023-12-10T14:31:25.707462Z",
"url": "https://files.pythonhosted.org/packages/0e/49/34b5e96674e5e970e662cf63bc57d9a7e6c705d175511672db5b56e91aaf/pya-0.5.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "48c489870b682fed797296555bbd27c97b91c3fab2a9f7fc8991ceeec1b30a40",
"md5": "e460b8d4331b070fc19412d9e9dfbb80",
"sha256": "f5ee5f06bc4f7a7683eaab564643ac9c80631385d8f89e4c2f1d105f1edaa4e7"
},
"downloads": -1,
"filename": "pya-0.5.2.tar.gz",
"has_sig": false,
"md5_digest": "e460b8d4331b070fc19412d9e9dfbb80",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 1582680,
"upload_time": "2023-12-10T14:31:28",
"upload_time_iso_8601": "2023-12-10T14:31:28.581714Z",
"url": "https://files.pythonhosted.org/packages/48/c4/89870b682fed797296555bbd27c97b91c3fab2a9f7fc8991ceeec1b30a40/pya-0.5.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-12-10 14:31:28",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "interactive-sonification",
"github_project": "pya",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"appveyor": true,
"requirements": [],
"tox": true,
"lcname": "pya"
}