This repository was archived by the owner on Jul 27, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathtest.rs
137 lines (115 loc) · 4.61 KB
/
test.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//!
//! test.rs.rs
//!
//! Created by Mitchell Nordine at 05:57PM on December 19, 2014.
//!
//! Always remember to run high performance Rust code with the --release flag. `Synth`
//!
extern crate pitch_calc as pitch;
extern crate portaudio;
extern crate sample;
extern crate synth;
use portaudio as pa;
use pitch::{Letter, LetterOctave};
use synth::Synth;
// Currently supports i8, i32, f32.
pub type AudioSample = f32;
pub type Input = AudioSample;
pub type Output = AudioSample;
const CHANNELS: i32 = 2;
const FRAMES: u32 = 64;
const SAMPLE_HZ: f64 = 44_100.0;
fn main() {
run().unwrap()
}
fn run() -> Result<(), pa::Error> {
// Construct our fancy Synth!
let mut synth = {
use synth::{Point, Oscillator, oscillator, Envelope};
// The following envelopes should create a downward pitching sine wave that gradually quietens.
// Try messing around with the points and adding some of your own!
let amp_env = Envelope::from(vec!(
// Time , Amp , Curve
Point::new(0.0 , 0.0 , 0.0),
Point::new(0.01 , 1.0 , 0.0),
Point::new(0.45 , 1.0 , 0.0),
Point::new(0.81 , 0.8 , 0.0),
Point::new(1.0 , 0.0 , 0.0),
));
let freq_env = Envelope::from(vec!(
// Time , Freq , Curve
Point::new(0.0 , 0.0 , 0.0),
Point::new(0.00136 , 1.0 , 0.0),
Point::new(0.015 , 0.02 , 0.0),
Point::new(0.045 , 0.005 , 0.0),
Point::new(0.1 , 0.0022 , 0.0),
Point::new(0.35 , 0.0011 , 0.0),
Point::new(1.0 , 0.0 , 0.0),
));
// Now we can create our oscillator from our envelopes.
// There are also Sine, Noise, NoiseWalk, SawExp and Square waveforms.
let oscillator = Oscillator::new(oscillator::waveform::Square, amp_env, freq_env, ());
// Here we construct our Synth from our oscillator.
Synth::retrigger(())
.oscillator(oscillator) // Add as many different oscillators as desired.
.duration(6000.0) // Milliseconds.
.base_pitch(LetterOctave(Letter::C, 1).hz()) // Hz.
.loop_points(0.49, 0.51) // Loop start and end points.
.fade(500.0, 500.0) // Attack and Release in milliseconds.
.num_voices(16) // By default Synth is monophonic but this gives it `n` voice polyphony.
.volume(0.2)
.detune(0.5)
.spread(1.0)
// Other methods include:
// .loop_start(0.0)
// .loop_end(1.0)
// .attack(ms)
// .release(ms)
// .note_freq_generator(nfg)
// .oscillators([oscA, oscB, oscC])
// .volume(1.0)
};
// Construct a note for the synth to perform. Have a play around with the pitch and duration!
let note = LetterOctave(Letter::C, 1);
let note_velocity = 1.0;
synth.note_on(note, note_velocity);
// We'll call this to release the note after 4 seconds.
let note_duration = 4.0;
let mut is_note_off = false;
// We'll use this to keep track of time and break from the loop after 6 seconds.
let mut timer: f64 = 0.0;
// This will be used to determine the delta time between calls to the callback.
let mut prev_time = None;
// The callback we'll use to pass to the Stream.
let callback = move |pa::OutputStreamCallbackArgs { buffer, time, .. }| {
let buffer: &mut [[f32; CHANNELS as usize]] = sample::slice::to_frame_slice_mut(buffer).unwrap();
sample::slice::equilibrium(buffer);
synth.fill_slice(buffer, SAMPLE_HZ as f64);
if timer < 6.0 {
let last_time = prev_time.unwrap_or(time.current);
let dt = time.current - last_time;
timer += dt;
prev_time = Some(time.current);
// Once the timer exceeds our note duration, send the note_off.
if timer > note_duration {
if !is_note_off {
synth.note_off(note);
is_note_off = true;
}
}
pa::Continue
} else {
pa::Complete
}
};
// Construct PortAudio and the stream.
let pa = try!(pa::PortAudio::new());
let settings = try!(pa.default_output_stream_settings::<f32>(CHANNELS, SAMPLE_HZ, FRAMES));
let mut stream = try!(pa.open_non_blocking_stream(settings, callback));
try!(stream.start());
// Loop while the stream is active.
while let Ok(true) = stream.is_active() {
std::thread::sleep(std::time::Duration::from_millis(16));
}
Ok(())
}