Skip to content

Commit

Permalink
Merge pull request #57 from mitchmindtree/signal
Browse files Browse the repository at this point in the history
 Change the `Signal` trait to return `Self::Frame` rather than `Option<Self::Item>`
  • Loading branch information
mitchmindtree authored Jul 14, 2017
2 parents 0e00a97 + d6680a0 commit 0d992d9
Show file tree
Hide file tree
Showing 10 changed files with 711 additions and 730 deletions.
27 changes: 14 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,38 +50,39 @@ let bar: [u8; 2] = foo.map(Sample::to_sample);
assert_eq!(bar, [128u8, 128]);
```

Use the **Signal** trait for working with `Iterator`s that yield `Frame`s.
To complement the `Iterator` trait, **Signal** provides methods for adding,
scaling, offsetting, multiplying, clipping and generating frame iterators and
more. Working with **Signal**s allows for easy, readable creation of rich and
complex DSP graphs with a simple and familiar API.
Use the **Signal** trait for working with infinite-iterator-like types that
yield `Frame`s. **Signal** provides methods for adding, scaling, offsetting,
multiplying, clipping and generating streams of `Frame`s. Working with
**Signal**s allows for easy, readable creation of rich and complex DSP graphs
with a simple and familiar API.

```rust
// Clip to an amplitude of 0.9.
let frames = [[1.2, 0.8], [-0.7, -1.4]];
let clipped: Vec<_> = frames.iter().cloned().clip_amp(0.9).collect();
let clipped: Vec<_> = signal::from_slice(&frames).clip_amp(0.9).take(2).collect();
assert_eq!(clipped, vec![[0.9, 0.8], [-0.7, -0.9]]);

// Add `a` with `b` and yield the result.
let a = [[0.2], [-0.6], [0.5]];
let b = [[0.2], [0.1], [-0.8]];
let a_signal = a.iter().cloned();
let b_signal = b.iter().cloned();
let added: Vec<[f32; 1]> = a_signal.add_amp(b_signal).collect();
let a_signal = signal::from_slice(&a);
let b_signal = signal::from_slice(&b);
let added: Vec<[f32; 1]> = a_signal.add_amp(b_signal).take(3).collect();
assert_eq!(added, vec![[0.4], [-0.5], [-0.3]]);

// Scale the playback rate by `0.5`.
let foo = [[0.0], [1.0], [0.0], [-1.0]];
let mut source = foo.iter().cloned();
let interp = Linear::from_source(&mut source).unwrap();
let frames: Vec<_> = source.scale_hz(interp, 0.5).collect();
let mut source = signal::from_slice(&foo);
let interp = Linear::from_source(&mut source);
let frames: Vec<_> = source.scale_hz(interp, 0.5).take(8).collect();
assert_eq!(&frames[..], &[[0.0], [0.5], [1.0], [0.5], [0.0], [-0.5], [-1.0], [-0.5]][..]);
```

The **signal** module also provides a series of **Signal** source types,
including:

- `FromInterleavedSamples`
- `FromIterator`
- `FromInterleavedSamplesIterator`
- `Equilibrium` (silent signal)
- `Phase`
- `Sine`
Expand Down
9 changes: 6 additions & 3 deletions examples/resample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ extern crate sample;

use hound::{WavReader, WavSpec, WavWriter};
use sample::interpolate::{Sinc, Converter};
use sample::Sample;
use sample::{signal, Sample, Signal};

fn main() {
let assets = find_folder::Search::ParentsThenKids(5, 5).for_folder("assets").unwrap();
let mut reader = WavReader::open(assets.join("two_vowels.wav")).unwrap();
let samples: Vec<[f64; 1]> = reader.samples::<i16>()
.map(|s| [s.unwrap().to_sample()])
.collect();
let len = samples.len();
let signal = signal::from_slice(&samples[..]);

let sample_rate = reader.spec().sample_rate as f64;
let new_sample_rate = 10_000.0;
let sinc = Sinc::zero_padded(50);
let conv = Converter::from_hz_to_hz(samples.iter().cloned(), sinc, sample_rate, new_sample_rate);
let conv = Converter::from_hz_to_hz(signal, sinc, sample_rate, new_sample_rate);

let spec = WavSpec {
channels: 1,
Expand All @@ -26,7 +28,8 @@ fn main() {
};

let mut writer = WavWriter::create(assets.join("two_vowels_10k.wav"), spec).unwrap();
for f in conv {
let len = (len as f64 * new_sample_rate / sample_rate) as usize;
for f in conv.take(len) {
writer.write_sample((f[0].to_sample::<i16>())).unwrap();
}
}
10 changes: 4 additions & 6 deletions examples/synth.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
extern crate portaudio as pa;
extern crate sample;

use sample::{Frame, Sample, Signal, ToFrameSliceMut};
use sample::signal;
use sample::{signal, Frame, Sample, Signal, ToFrameSliceMut};

const FRAMES_PER_BUFFER: u32 = 512;
const NUM_CHANNELS: i32 = 1;
Expand All @@ -17,13 +16,12 @@ fn run() -> Result<(), pa::Error> {
// Create a signal chain to play back 1 second of each oscillator at A4.
let hz = signal::rate(SAMPLE_RATE).const_hz(440.0);
let one_sec = SAMPLE_RATE as usize;
let mut signal = hz.clone().sine().take(one_sec)
let mut waves = hz.clone().sine().take(one_sec)
.chain(hz.clone().saw().take(one_sec))
.chain(hz.clone().square().take(one_sec))
.chain(hz.clone().noise_simplex().take(one_sec))
.chain(signal::noise(0).take(one_sec))
.map(|f| f.map(|s| s.to_sample::<f32>()))
.scale_amp(0.2);
.map(|f| f.map(|s| s.to_sample::<f32>() * 0.2));

// Initialise PortAudio.
let pa = try!(pa::PortAudio::new());
Expand All @@ -35,7 +33,7 @@ fn run() -> Result<(), pa::Error> {
let callback = move |pa::OutputStreamCallbackArgs { buffer, .. }| {
let buffer: &mut [[f32; 1]] = buffer.to_frame_slice_mut().unwrap();
for out_frame in buffer {
match signal.next() {
match waves.next() {
Some(frame) => *out_frame = frame,
None => return pa::Complete,
}
Expand Down
7 changes: 5 additions & 2 deletions examples/wav.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,12 @@ fn frames(file_name: &'static str) -> Vec<wav::Frame> {
let sample_file = assets.join(file_name);
let mut reader = hound::WavReader::open(&sample_file).unwrap();
let spec = reader.spec();
let duration = reader.duration();
let new_duration = (duration as f64 * (SAMPLE_RATE as f64 / spec.sample_rate as f64)) as usize;
let samples = reader.samples().map(|s| s.unwrap());
let mut signal = signal::from_interleaved_samples::<_, wav::Frame>(samples);
let interp = Linear::from_source(&mut signal).unwrap();
let mut signal = signal::from_interleaved_samples_iter::<_, wav::Frame>(samples);
let interp = Linear::from_source(&mut signal);
signal.from_hz_to_hz(interp, spec.sample_rate as f64, SAMPLE_RATE as f64)
.take(new_duration)
.collect()
}
Loading

0 comments on commit 0d992d9

Please sign in to comment.