https://github.com/Quefumas/gensound
Pythonic audio processing and generation framework
https://github.com/Quefumas/gensound
audio audio-effect audio-processing audio-synthesis dsp music music-composition sound
Last synced: 12 months ago
JSON representation
Pythonic audio processing and generation framework
- Host: GitHub
- URL: https://github.com/Quefumas/gensound
- Owner: Quefumas
- License: apache-2.0
- Created: 2020-09-26T22:01:35.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2022-11-26T22:08:21.000Z (over 3 years ago)
- Last Synced: 2024-10-05T08:18:21.242Z (over 1 year ago)
- Topics: audio, audio-effect, audio-processing, audio-synthesis, dsp, music, music-composition, sound
- Language: Python
- Homepage:
- Size: 5.88 MB
- Stars: 80
- Watchers: 4
- Forks: 6
- Open Issues: 11
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# Gensound
The Python way to audio processing & synthesis.
An intuitive, flexible and lightweight library for:
* Experimenting with audio and signal processing
* Creating and manipulating sounds
* Electronic composition
Core features:
* Platform independent
* Very intuitive syntax
* Easy to create new effects or experiments and combine them with existing features
* Great for learning about audio and signals
* Multi-channel audio for customizable placement of sound sources
* Parametrization
* And more to come!
## Setup
1. Install using `pip install gensound`.
This will also ensure NumPy is installed.
For smoother playback, it is also recommended to have any one of
[simpleaudio](https://github.com/hamiltron/py-simple-audio),
[playsound](https://github.com/TaylorSMarks/playsound),
[PyGame](https://www.pygame.org) installed.
It is also recommended to have [FFMPEG](https://ffmpeg.org/) installed,
which enables read/export of file formats other than Wave and AIFF.
2. Run the examples below (or some of the example files in the repository).
## Gensound in less than a minute
All audio is a mixture of signals (audio streams), to which we can apply transforms (effects).
* To apply a transform to a signal we use the syntax: `Signal * Transform`;
* To mix two signals together we use addition: `Signal + Signal`;
* And to concatenate two signals (play one after the other): `Signal | Signal`.
Each of these operations results in a new `Signal` object on which we can perform more of these operations.
Now, let's run some basic examples!
## Show Me the Code
* Load a WAV into a `Signal` object from a file:
```python
from gensound import WAV, test_wav
wav = WAV(test_wav) # load sample WAV, included with gensound
```
* Playback or file export:
```python
wav.play()
wav.export("test.wav")
```
* Play file using different sample rate (results in pitch shift):
```python
wav.play(sample_rate=32000) # original sample rate 44.1 kHz
```
* Play only the R channel:
```python
wav[1].play() # wav[0] is L channel, wav[1] is R
```
* Turn down the volume of L channel:
```python
wav[0] *= 0.5 # amplitude halved; wav[1] amplitude remains the same
wav.play()
```
* Same thing, but using [dBs](https://en.wikipedia.org/wiki/Decibel):
```python
from gensound import Gain
wav[0] *= Gain(-3) # apply Gain transform to attenuate by 3 dB
```
* Mix a Stereo signal (L-R channels) to mono (center channel only):
```python
wav = 0.5*wav[0] + 0.5*wav[1] # sums up L and R channels together, halving the amplitudes
```
* Switch L/R channels:
```python
wav[0], wav[1] = wav[1], wav[0]
```
* Crop 5 seconds from the beginning (`5e3` is short for `5000.0`, meaning 5,000 milliseconds or 5 seconds):
```python
wav = wav[5e3:] # since 5e3 is float, gensound knows we are not talking about channels
```
If we only care about the R channel:
```python
wav = wav[1, 5e3:] # 5 seconds onwards, R channel only
```
We can decide to slice using sample numbers (ints) instead of absolute time (floats):
```python
wav = wav[:,:1000] # grabs first 1000 samples in both channels; samples are in ints
```
* Repeat a signal 5 times:
```python
wav = wav**5
```
* Mix a 440Hz (middle A) sine wave to the L channel, 4 seconds after the beginning:
```python
from gensound import Sine
wav[0,4e3:] += Sine(frequency=440, duration=2e3)*Gain(-9)
```
* Play a tune (see full syntax [here](https://github.com/Quefumas/gensound/wiki/Melodic-Shorthand-Notation)):
```python
s = Sine('D5 C# A F# B G# E# C# F#', duration=0.5e3)
s.play()
```
* Reverse the R channel:
```python
from gensound import Reverse
wav[1] *= Reverse()
```
* [Haas effect](https://en.wikipedia.org/wiki/Precedence_effect) - delaying the L channel by several samples makes the sound appear to be coming from the right:
```python
from gensound import Shift
wav[0] *= Shift(80) # try changing the number of samples
# when listening, pay attention to the direction the audio appears to be coming from
```
* Stretch effect - slowing down or speeding up the signal by stretching or shrinking it. This affects pitch as well:
```python
from gensound.effects import Stretch
wav *= Stretch(rate=1.5) # plays the Signal 1.5 times as fast
wav *= Stretch(duration=30e3) # alternative syntax: fit the Signal into 30 seconds
```
* Advanced: AutoPan both L/R channels with different frequency and depth:
```python
from gensound.curve import SineCurve
s = WAV(test_wav)[10e3:30e3] # pick 20 seconds of audio
curveL = SineCurve(frequency=0.2, depth=50, baseline=-50, duration=20e3)
# L channel will move in a Sine pattern between -100 (Hard L) and 0 (C)
curveR = SineCurve(frequency=0.12, depth=100, baseline=0, duration=20e3)
# R channel will move in a Sine pattern (different frequency) between -100 and 100
t = s[0]*Pan(curveL) + s[1]*Pan(curveR)
```
## Syntax Cheatsheet
Meet the two core classes:
* `Signal` - a stream of multi-channeled samples, either raw (e.g. loaded from WAV file) or mathematically computable (e.g. a Sawtooth wave). Behaves very much like a `numpy.ndarray`.
* `Transform` - any process that can be applied to a Signal (for example, reverb, filtering, gain, reverse, slicing).
**By combining Signals in various ways and applying Transforms to them, we can generate anything.**
Signals are envisioned as mathematical objects, and Gensound relies greatly on overloading of arithmetic operations on them, in conjunction with Transforms.
All of the following expressions return a new Signal object:
* `amplitude*Signal`: change Signal's amplitude (loudness) by a given factor (float)
* `-Signal`: inverts the Signal
* `Signal + Signal`: mix two Signals together
* `Signal | Signal`: concatenate two Signals one after the other
* `Signal**4`: repeat the Signal 4 times
* `Signal*Transform`: apply `Transform` to `Signal`
* `Signal[start_channel:end_channel,start_ms:end_ms]`: `Signal` sliced to a certain range of channels and time (in ms). The first slice expects integers; the second expects floats.
* `Signal[start_channel:end_channel,start_sample:end_sample]`: When the second slice finds integers instead of floats, it is interpreted as a range over samples instead of milliseconds.
Note that the duration of this Signal changes according to the sample rate.
* `Signal[start_channel:end_channel]`: when a single slice of ints is given, it is taken to mean the channels.
* `Signal[start_ms:end_ms]`: if the slice is made up of floats, it is interpreted as timestamps, i.e.: `Signal[:,start_ms:end_ms]`.
The slice notations may also be used for assignments:
```python
wav[4e3:4.5e3] = Sine(frequency=1e3, duration=0.5e3) # censor beep on seconds 4-4.5
wav[0,6e3:] *= Vibrato(frequency=4, width=0.5) # add vibrato effect to L channel starting from second 6
```
...and to increase the number of channels implicitly:
```python
wav = WAV("mono_audio.wav") # mono Signal object
wav[1] = -wav[0] # now a stereo Signal with R being a phase inverted version of L
```
> Note the convention that floats represent time as milliseconds, while integers represent number of samples.
When performing playback or file export of a Signal,
Gensound resolves the Signal tree recursively, combining the various Signals and applying the transforms.
## More
I would love to hear about your experience using Gensound - what worked well, what didn't, what do you think is missing.
Don't hesitate to [drop me a line](https://github.com/Quefumas/gensound/discussions).
The gradually evolving [Wiki](https://github.com/Quefumas/gensound/wiki) is both a tutorial and a reference,
and will also provide many fun examples to learn and play with.
If you are interested in contributing, check out [Contribution](CONTRIBUTING.md).