Skip to content

Commit

Permalink
Merge pull request #122 from mitchmindtree/dag
Browse files Browse the repository at this point in the history
Switch from using petgraph directly to the daggy crate. Massively improve API. Add documentation link.
  • Loading branch information
mitchmindtree committed Oct 9, 2015
2 parents d9448cd + 10df76f commit 7ebbe65
Show file tree
Hide file tree
Showing 7 changed files with 633 additions and 372 deletions.
32 changes: 17 additions & 15 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
language: rust
rust:
- nightly
- stable
- nightly
- stable
notifications:
email:
- [email protected]
email:
- [email protected]
os:
- linux
- osx
- linux
env:
- LD_LIBRARY_PATH: /usr/local/lib
matrix:
- LD_LIBRARY_PATH: /usr/local/lib
global:
secure: H/FCcjwpQQNeWGRM6zrDojNwRJud/FsAu5N6iGz2kxog0v7FFSuFreYeklNfwX+4Mf+BtYYpblZ8xHF24tOmJHeOMKwGPBoopyjXzJx+QVd3mlj30dmvm1/jcy/7pzH0Q2GhVhSbBtV+BCQvjUXZ/PNk9/wiMSxnNtTchyAOpHQ=
install:
- curl -O http://www.portaudio.com/archives/pa_stable_v19_20140130.tgz
- tar xfz pa_stable_v19_20140130.tgz
- (cd portaudio/ && ./configure && make && sudo make install)
- curl -O http://www.portaudio.com/archives/pa_stable_v19_20140130.tgz
- tar xfz pa_stable_v19_20140130.tgz
- (cd portaudio/ && ./configure && make && sudo make install)
before_script:
- rustc --version
- cargo --version
- rustc --version
- cargo --version
script:
- cargo build --verbose
- cargo test --verbose
- cargo doc --verbose
- cargo build --verbose
- cargo test --verbose
- cargo doc --verbose
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

name = "dsp-chain"
version = "0.6.0"
version = "0.7.0"
authors = [
"mitchmindtree <[email protected]>",
"bvssvni <[email protected]>",
Expand All @@ -21,6 +21,6 @@ name = "dsp"
path = "./src/lib.rs"

[dependencies]
daggy = "0.1.3"
num = { version = "0.1.27", default-features = false }
petgraph = "0.1.11"
sound_stream = "0.4.4"
33 changes: 19 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# dsp-chain [![Build Status](https://travis-ci.org/RustAudio/dsp-chain.svg?branch=master)](https://travis-ci.org/RustAudio/dsp-chain)
# dsp-chain [![Build Status](https://travis-ci.org/RustAudio/dsp-chain.svg?branch=master)](https://travis-ci.org/RustAudio/dsp-chain) [![Crates.io](https://img.shields.io/crates/v/dsp-chain.svg)](https://crates.io/crates/dsp-chain) [![Crates.io](https://img.shields.io/crates/l/dsp-chain.svg)](https://github.com/RustAudio/dsp-chain/blob/master/LICENSE)

A simple library for chaining together multiple audio dsp processors/generators, written in Rust!

A library for chaining together multiple audio dsp processors/generators, written in Rust!

Use cases for dsp-chain include:
- Designing effects.
Expand All @@ -10,31 +11,35 @@ Use cases for dsp-chain include:
- Any kind of modular audio synthesis/processing.


Documenation
------------

[API documentation here!](http://RustAudio.github.io/dsp-chain/dsp)


Usage
-----

Here's what it looks like:

```Rust
// Construct our dsp graph.
let mut dsp_graph = Graph::new();
let mut graph = Graph::new();

// Construct our fancy Synth and add it to the graph!
let synth = dsp_graph.add_node(DspNode::Synth);
let synth = graph.add_node(DspNode::Synth);

// Construct a few oscillators, add them to the graph and connect them to the synth.
let oscillator_a = dsp_graph.add_node(DspNode::Oscillator(0.0, A5_HZ, 0.2));
let oscillator_b = dsp_graph.add_node(DspNode::Oscillator(0.0, D5_HZ, 0.1));
let oscillator_c = dsp_graph.add_node(DspNode::Oscillator(0.0, F5_HZ, 0.15));
dsp_graph.add_input(oscillator_a, synth).unwrap();
dsp_graph.add_input(oscillator_b, synth).unwrap();
dsp_graph.add_input(oscillator_c, synth).unwrap();
// Add a few oscillators as inputs to the synth.
graph.add_input(DspNode::Oscillator(0.0, A5_HZ, 0.2), synth);
graph.add_input(DspNode::Oscillator(0.0, D5_HZ, 0.1), synth);
graph.add_input(DspNode::Oscillator(0.0, F5_HZ, 0.15), synth);

// Set the synth as the master node for the graph.
dsp_graph.set_master(Some(synth));
// This can be inferred by the graph so calling this is optional, but it's nice to be explicit.
graph.set_master(Some(synth));

// Request audio from our Graph.
dsp_graph.audio_requested(&mut buffer, settings);
graph.audio_requested(&mut buffer, settings);
```

Here are [two working examples](https://github.com/PistonDevelopers/dsp-chain/blob/master/examples) of using dsp-chain to create a very basic synth and an oscillating volume.
Expand All @@ -50,7 +55,7 @@ dsp-chain = "*"
PortAudio
---------

dsp-chain uses [PortAudio](http://www.portaudio.com) as a cross-platform audio backend. The [rust-portaudio](https://github.com/jeremyletang/rust-portaudio) dependency will first try to find an already installed version on your system before trying to download it and build PortAudio itself.
The dsp-chain examples uses [PortAudio](http://www.portaudio.com) as a cross-platform audio backend. The [rust-portaudio](https://github.com/jeremyletang/rust-portaudio) dependency will first try to find an already installed version on your system before trying to download it and build PortAudio itself.


License
Expand Down
32 changes: 17 additions & 15 deletions examples/synth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,40 +23,42 @@ const F5_HZ: Frequency = 698.46;
fn main() {

// Construct our dsp graph.
let mut dsp_graph = Graph::new();
let mut graph = Graph::new();

// Construct our fancy Synth and add it to the graph!
let synth = dsp_graph.add_node(DspNode::Synth);
let synth = graph.add_node(DspNode::Synth);

// Construct a few oscillators, add them to the graph and connect them to the synth.
let oscillator_a = dsp_graph.add_node(DspNode::Oscillator(0.0, A5_HZ, 0.2));
let oscillator_b = dsp_graph.add_node(DspNode::Oscillator(0.0, D5_HZ, 0.1));
let oscillator_c = dsp_graph.add_node(DspNode::Oscillator(0.0, F5_HZ, 0.15));
dsp_graph.add_input(oscillator_a, synth).unwrap();
dsp_graph.add_input(oscillator_b, synth).unwrap();
dsp_graph.add_input(oscillator_c, synth).unwrap();
// Connect a few oscillators to the synth.
let (_, oscillator_a) = graph.add_input(DspNode::Oscillator(0.0, A5_HZ, 0.2), synth);
graph.add_input(DspNode::Oscillator(0.0, D5_HZ, 0.1), synth);
graph.add_input(DspNode::Oscillator(0.0, F5_HZ, 0.15), synth);

// If adding a connection between two nodes would create a cycle, Graph will return an Err.
if let Err(err) = dsp_graph.add_input(synth, oscillator_a) {
println!("Test for graph cycle error: {:?}", ::std::error::Error::description(&err));
if let Err(err) = graph.add_connection(synth, oscillator_a) {
println!("Testing for cycle error: {:?}", ::std::error::Error::description(&err));
}

// Set the synth as the master node for the graph.
dsp_graph.set_master(Some(synth));
graph.set_master(Some(synth));

// We'll use this to count down from three seconds and then break from the loop.
let mut timer: f64 = 3.0;

// The callback we'll use to pass to the Stream. It will request audio from our dsp_graph.
let callback = Box::new(move |output: &mut[Output], settings: Settings, dt: f64, _: CallbackFlags| {
Sample::zero_buffer(output);
dsp_graph.audio_requested(output, settings);
graph.audio_requested(output, settings);
timer -= dt;
for input in dsp_graph.inputs_mut(synth) {
if let DspNode::Oscillator(_, ref mut pitch, _) = *input {

// Traverse inputs or outputs of a node with the following pattern.
let mut inputs = graph.walk_inputs(synth);
while let Some(input_idx) = inputs.next_node(&mut graph) {
if let DspNode::Oscillator(_, ref mut pitch, _) = graph[input_idx] {
// Pitch down our oscillators for fun.
*pitch -= 0.1;
}
}

if timer >= 0.0 { CallbackResult::Continue } else { CallbackResult::Complete }
});

Expand Down
19 changes: 8 additions & 11 deletions examples/volume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,31 @@ use dsp::{CallbackFlags, CallbackResult, Graph, Node, Sample,
fn main() {

// Construct our dsp graph.
let mut dsp_graph = Graph::new();
let mut graph = Graph::new();

// Construct our fancy Synth and add it to the graph!
let synth = dsp_graph.add_node(DspNode::Synth(0.0));
let synth = graph.add_node(DspNode::Synth(0.0));

// Construct our volume node.
let volume = dsp_graph.add_node(DspNode::Volume(1.0));

// Plug the synth into our Volume node.
dsp_graph.add_input(synth, volume).unwrap();
// Output our synth to a marvellous volume node.
let (_, volume) = graph.add_output(synth, DspNode::Volume(1.0));

// Set the synth as the master node for the graph.
dsp_graph.set_master(Some(volume));
graph.set_master(Some(volume));

// We'll use this to count down from three seconds and then break from the loop.
let mut timer: f64 = 0.0;

// The callback we'll use to pass to the Stream. It will request audio from our dsp_graph.
// The callback we'll use to pass to the Stream. It will request audio from our graph.
let callback = Box::new(move |output: &mut[f32], settings: Settings, dt: f64, _: CallbackFlags| {

// Zero the sample buffer.
Sample::zero_buffer(output);

// Request audio from the graph.
dsp_graph.audio_requested(output, settings);
graph.audio_requested(output, settings);

// Oscillate the volume.
if let &mut DspNode::Volume(ref mut vol) = &mut dsp_graph[volume] {
if let &mut DspNode::Volume(ref mut vol) = &mut graph[volume] {
*vol = (4.0 * timer as f32).sin();
}

Expand Down
Loading

0 comments on commit 7ebbe65

Please sign in to comment.