-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
258 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Accessing in memory | ||
|
||
The floating-point samples within a SignalFlow `Buffer` can be read and written directly from Python. | ||
|
||
## Using get and set methods | ||
|
||
The `get()` and `set()` methods can be used to access individual samples, indexed by channel and frame offset. | ||
|
||
```python | ||
# Create a 2-channel buffer | ||
buf = Buffer(2, 256) | ||
|
||
# Set the sample in channel 1 at index 20 to 0.5 | ||
buf.set(1, 20, 0.5) | ||
|
||
# Confirm that the sample is set correctly | ||
assert buf.get(1, 20) == 0.5 | ||
``` | ||
|
||
## As a numpy array | ||
|
||
The `.data` property of a `Buffer` points to a numpy array of shape `(num_channels, num_frames)`, which can be used to read or write the buffer's data in real time. | ||
|
||
```python | ||
import time | ||
|
||
# Create and play a one-second silent buffer | ||
buf = Buffer(2, graph.sample_rate) | ||
player = BufferPlayer(buf, loop=True) | ||
player.play() | ||
|
||
# Gradually add crackles to the buffer, which will be heard in real-time | ||
while True: | ||
buf.data[0][np.random.randint(0, graph.sample_rate)] = 1.0 | ||
buf.data[1][np.random.randint(0, graph.sample_rate)] = 1.0 | ||
time.sleep(1) | ||
``` | ||
|
||
## Filling a buffer with the result of a function | ||
|
||
Just like when [creating a buffer](creating.md#initialising-a-buffer-with-the-result-of-a-function), an existing buffer can be filled with the output of a Python function. | ||
|
||
|
||
|
||
--- | ||
|
||
[→ Next: Arithmetic operators](operators.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# Creating a Buffer | ||
|
||
A Buffer can be created from: | ||
|
||
- [a sound file](#loading-a-buffer-from-a-sound-file) | ||
- [an array of samples](#creating-a-buffer-from-an-array-of-samples) | ||
- [a specified dimension](#creating-an-empty-buffer) | ||
- [the result of a function](#initialising-a-buffer-with-the-result-of-a-function) | ||
|
||
## Loading a buffer from a sound file | ||
|
||
To load an audio buffer from a sound file, pass the file path to Buffer's constructor. | ||
|
||
```python | ||
# Load and play a buffer | ||
buf = Buffer("filename.wav") | ||
player = BufferPlayer(buf) | ||
player.play() | ||
``` | ||
|
||
The type of the audio file is automatically inferred from the type and contents. Supported formats include `wav`, `aif`, `mp3`, `ogg`, `flac`, and many other audio formats. | ||
|
||
Interally, file I/O is handled by `libsndfile`. For a full list of supported files, see the [libsndfile documentation](http://www.mega-nerd.com/libsndfile/). | ||
|
||
--- | ||
|
||
## Creating a buffer from an array of samples | ||
|
||
To create and initialise a buffer from an existing array of samples, pass the array to Buffer's constructor. Both native Python arrays and `numpy` arrays are supported. | ||
|
||
Note that audio samples should always range between `-1.0` and `1.0` to avoid distortion. | ||
|
||
```python | ||
# Initialise a buffer from a native 1D array containing a sawtooth wave | ||
samples = [(n % 100) / 100 - 0.5 for n in range(44100)] | ||
buf = Buffer(samples) | ||
player = BufferPlayer(buf) | ||
player.play() | ||
``` | ||
|
||
If the array is 1D, a mono buffer will be created. If the array is 2D, a multichannel buffer will be created. | ||
|
||
```python | ||
# Initialise a buffer from a numpy 2D array containing a stereo sine wave | ||
import numpy as np | ||
|
||
t = np.linspace(0, 1, 44100) | ||
stereo = np.array([np.sin(220 * t * np.pi * 2), | ||
np.sin(225 * t * np.pi * 2)]) | ||
buf = Buffer(stereo * 0.1) | ||
player = BufferPlayer(buf) | ||
player.play() | ||
``` | ||
|
||
--- | ||
|
||
## Creating an empty buffer | ||
|
||
An empty buffer can be initialised by specifying its dimensions. All samples will be initialised to zero. | ||
|
||
```python | ||
# Create an empty buffer with 2 channels containing 44100 samples each. | ||
buf = Buffer(2, 44100) | ||
``` | ||
|
||
--- | ||
|
||
## Initialising a buffer with the result of a function | ||
|
||
A buffer can also be populated with the result of a Python function, which takes a single argument containing the index of the frame to be filled. | ||
|
||
```python | ||
# Create a buffer containing a 440Hz ping | ||
import numpy as np | ||
buf = Buffer(1, graph.sample_rate, | ||
lambda frame: np.sin(frame * 440 * np.pi * 2 / graph.sample_rate) * (1 - frame / graph.sample_rate)) | ||
player = BufferPlayer(buf) | ||
player.play() | ||
``` | ||
|
||
--- | ||
|
||
[→ Next: Saving and exporting a buffer](exporting.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Saving and exporting a buffer | ||
|
||
## Saving to a sound file | ||
|
||
To export a buffer's audio contents to a sound file, use the `save()` method: | ||
|
||
```python | ||
import numpy as np | ||
buf = Buffer(np.sin(np.linspace(0, 1, graph.sample_rate) * 440 * np.pi * 2)) | ||
buf.save("buffer.wav") | ||
``` | ||
|
||
The output format will be automatically detected from the filename extension. Supported formats are presently `wav`, `aif` and `flac`. | ||
|
||
--- | ||
|
||
[→ Next: Passing a buffer as an input to a node or patch](input.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,14 @@ | ||
# Buffer | ||
# Buffers | ||
|
||
!!! warning | ||
This documentation is a work-in-progress and may have sections that are missing or incomplete. | ||
A `Buffer` is an area of memory that stores single-channel or multi-channel data, which may represent an audio waveform or any other type of signal. | ||
|
||
A `Buffer` is an allocated area of memory that can be used to store single-channel or multi-channel data, which may represent an audio waveform or any other type of signal. | ||
|
||
- A Buffer can be created from a sound file, an array of samples, or with an empty contents | ||
- A Buffer can be passed to a Node or Patch as an input | ||
- A Buffer can be exported to a sound file | ||
- A Buffer's data can be directly accessed in memory as a numpy array, or by get/set methods | ||
- The contents of a buffer can be combined with arithmetic operators | ||
- Properties | ||
- Buffer interpolation modes | ||
- 2D buffers | ||
- Buffer applications: Sample recording and playback, control recording and playback, envelopes, waveshapers | ||
- The total Buffer memory usage can be queried | ||
- A Buffer can be [created](creating.md) from a sound file, an array of samples, a specified dimension, or the result of a function | ||
- A Buffer can be [saved to a sound file](exporting.md) | ||
- A Buffer can be [passed to a Node or Patch](input.md) as an input | ||
- Buffer [sample access](access.md) can be performed by get/set/fill methods, or directly as a numpy array | ||
- Buffers can be modified, combined and queried with standard [arithmetic operators](operators.md) | ||
- Buffers can be queried for a number of [properties](properties.md), including interpolation modes and total memory usage | ||
- _TODO_: Different Buffer subclasses exist for specific operations, including `Buffer2D`, `WaveshaperBuffer` and `EnvelopeBuffer` | ||
- _TODO_: Playing a buffer, including sample rate conversion and interpolation | ||
- _TODO_: Recording and rendering audio into a Buffer | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Passing a buffer as an input to a node or patch | ||
|
||
See: | ||
|
||
- [Node: Buffer inputs](../node/inputs.md#buffer-inputs) | ||
- [Patch: Buffer inputs](../patch/inputs.md#buffer-inputs) | ||
|
||
--- | ||
|
||
[→ Next: Accessing a buffer's data in memory](access.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Arithmetic operators | ||
|
||
Buffers, [like nodes](../node/operators.md), can be manipulated using Python's standard arithmetic operators. | ||
|
||
For example, to attenuate a buffer, it can be multiplied by a constant value. A new `Buffer` object is returned, with the same dimensions as the original, scaled by the coefficient. | ||
|
||
```python | ||
input_buffer = Buffer("input.wav") | ||
scaled_buffer = input_buffer * 0.5 | ||
# `scaled_buffer` now contains an attenuated version of `input_buffer` | ||
``` | ||
|
||
Below is a full list of operators supported by SignalFlow `Buffer` objects. | ||
|
||
| Operator | Node class | | ||
|----------|------------| | ||
| `+` | Add | | ||
| `-` | Subtract | | ||
| `*` | Multiply | | ||
| `/` | Divide | | ||
|
||
--- | ||
|
||
[→ Next: Buffer properties](properties.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Buffer properties | ||
|
||
A `Buffer` has a number of read-only properties which can be used to query its status at a given moment in time. | ||
|
||
| Property | Type | Description | | ||
|--------------------|-------|------------------------------------------------------------------------------------| | ||
| num_frames | int | The number of frames (samples) in the buffer. | | ||
| channels | int | The number of channels in the buffer. | | ||
| sample_rate | int | The sample rate of the buffer. | | ||
| duration | float | The duration of the buffer, in seconds. | | ||
| filename | str | If the buffer has been loaded from/saved to a file, the absolute path to the file. | | ||
| interpolation_mode | str | The interpolation mode of the buffer. [LINK] | | ||
|
||
--- | ||
|
||
[→ Next: Multichannel](multichannel.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters