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
|
// trriggy - a trigger/drum replacer in Rust
// Copyright (C) 2018 Harald Eilertsen <haraldei@anduin.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use hound;
use std::io::Read;
use std::iter::FromIterator;
#[derive(Default)]
struct Trigger {
trigged: bool,
playing: bool,
acc: u32,
sample_pos: usize,
sample: Vec<i16>,
}
impl Trigger {
pub fn new<T: Read>(samples: hound::WavReader<T>) -> Trigger {
Trigger::default().read_samples(samples)
}
fn read_samples<T: Read>(mut self, mut reader: hound::WavReader<T>) -> Trigger {
self.sample = Vec::from_iter(reader.samples().map(|s| s.unwrap()));
self
}
pub fn process(&mut self, sample: i16) -> i16 {
let mut res = 0i16;
let abs = sample.abs() as u32;
self.acc = (self.acc + abs) / 2;
if !self.trigged && self.acc > 1000 {
self.trigged = true;
self.playing = true;
self.sample_pos = 0;
}
else if self.trigged && self.acc < 50 {
self.trigged = false;
}
if self.playing {
res = self.sample[self.sample_pos];
self.sample_pos += 1;
}
if self.sample_pos > self.sample.len() {
self.playing = false;
}
res
}
}
fn print_wavspec<R: Read>(spec: &hound::WavSpec, r: &hound::WavReader<R>) {
println!(" channels: {}", spec.channels);
println!(" samplerate: {}", spec.sample_rate);
println!(" bits/sample: {}", spec.bits_per_sample);
println!(" sample format: {}", match spec.sample_format {
hound::SampleFormat::Int => "integer",
hound::SampleFormat::Float => "floating point",
});
println!(" duration: {} samples/{} sec/{} min",
r.duration(),
r.duration()/spec.sample_rate,
r.duration()/(spec.sample_rate * 60));
}
fn main() {
let filename = "test.wav";
let mut reader = hound::WavReader::open(&filename).unwrap();
println!("Reading file {}:", &filename);
let spec = reader.spec();
print_wavspec(&spec, &reader);
println!("Using sample file: {}", "bd.wav");
let mut sample_file = hound::WavReader::open("bd.wav").unwrap();
print_wavspec(&sample_file.spec(), &sample_file);
println!("Writing to output: {}", "output.wav");
let mut output = hound::WavWriter::create("output.wav", spec).unwrap();
let samples = reader.samples::<i16>();
let mut triggey = Trigger::new(sample_file);
samples
.map(|s| s.unwrap())
.for_each(|s| {
output.write_sample(triggey.process(s)).unwrap();
});
output.finalize().unwrap();
}
|