Skip to content

Commit 7969ce4

Browse files
committed
src/util: Add Samples::foreach_frame
Allows rapidly iterating the sample-buffers, one dasp::Frame at a time
1 parent 10f2792 commit 7969ce4

File tree

2 files changed

+45
-24
lines changed

2 files changed

+45
-24
lines changed

src/true_peak.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
use crate::interp::Interp;
2323

24-
use dasp_sample::{Sample, ToSample};
24+
use crate::utils::Sample;
2525

2626
/// True peak measurement.
2727
#[derive(Debug)]
@@ -68,7 +68,7 @@ impl TruePeak {
6868
self.interp.reset();
6969
}
7070

71-
pub fn check_true_peak<'a, T: Sample + ToSample<f32> + 'a, S: crate::Samples<'a, T>>(
71+
pub fn check_true_peak<'a, T: Sample + 'a, S: crate::Samples<'a, T>>(
7272
&mut self,
7373
src: &S,
7474
peaks: &mut [f64],

src/utils.rs

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2020
// THE SOFTWARE.
2121

22+
use dasp_frame::Frame;
23+
2224
/// Convert linear energy to logarithmic loudness.
2325
pub fn energy_to_loudness(energy: f64) -> f64 {
2426
// The non-test version is faster and more accurate but gives
@@ -35,11 +37,11 @@ pub fn energy_to_loudness(energy: f64) -> f64 {
3537
}
3638

3739
/// Trait for abstracting over interleaved and planar samples.
38-
pub trait Samples<'a, T: 'a>: Sized {
40+
pub trait Samples<'a, S: Sample + 'a>: Sized {
3941
/// Call the given closure for each sample of the given channel.
4042
// FIXME: Workaround for TrustedLen / TrustedRandomAccess being unstable
4143
// and because of that we wouldn't get nice optimizations
42-
fn foreach_sample(&self, channel: usize, func: impl FnMut(&'a T));
44+
fn foreach_sample(&self, channel: usize, func: impl FnMut(&'a S));
4345

4446
/// Call the given closure for each sample of the given channel.
4547
// FIXME: Workaround for TrustedLen / TrustedRandomAccess being unstable
@@ -48,9 +50,11 @@ pub trait Samples<'a, T: 'a>: Sized {
4850
&self,
4951
channel: usize,
5052
iter: impl Iterator<Item = U>,
51-
func: impl FnMut(&'a T, U),
53+
func: impl FnMut(&'a S, U),
5254
);
5355

56+
fn foreach_frame<F: Frame<Sample = S>>(&self, func: impl FnMut(F));
57+
5458
/// Number of frames.
5559
fn frames(&self) -> usize;
5660

@@ -62,16 +66,16 @@ pub trait Samples<'a, T: 'a>: Sized {
6266
}
6367

6468
/// Struct representing interleaved samples.
65-
pub struct Interleaved<'a, T> {
69+
pub struct Interleaved<'a, S> {
6670
/// Interleaved sample data.
67-
data: &'a [T],
71+
data: &'a [S],
6872
/// Number of channels.
6973
channels: usize,
7074
}
7175

72-
impl<'a, T> Interleaved<'a, T> {
76+
impl<'a, S> Interleaved<'a, S> {
7377
/// Create a new wrapper around the interleaved channels and do a sanity check.
74-
pub fn new(data: &'a [T], channels: usize) -> Result<Self, crate::Error> {
78+
pub fn new(data: &'a [S], channels: usize) -> Result<Self, crate::Error> {
7579
if channels == 0 {
7680
return Err(crate::Error::NoMem);
7781
}
@@ -84,9 +88,9 @@ impl<'a, T> Interleaved<'a, T> {
8488
}
8589
}
8690

87-
impl<'a, T> Samples<'a, T> for Interleaved<'a, T> {
91+
impl<'a, S: Sample> Samples<'a, S> for Interleaved<'a, S> {
8892
#[inline]
89-
fn foreach_sample(&self, channel: usize, mut func: impl FnMut(&'a T)) {
93+
fn foreach_sample(&self, channel: usize, mut func: impl FnMut(&'a S)) {
9094
assert!(channel < self.channels);
9195

9296
for v in self.data.chunks_exact(self.channels) {
@@ -99,7 +103,7 @@ impl<'a, T> Samples<'a, T> for Interleaved<'a, T> {
99103
&self,
100104
channel: usize,
101105
iter: impl Iterator<Item = U>,
102-
mut func: impl FnMut(&'a T, U),
106+
mut func: impl FnMut(&'a S, U),
103107
) {
104108
assert!(channel < self.channels);
105109

@@ -108,6 +112,14 @@ impl<'a, T> Samples<'a, T> for Interleaved<'a, T> {
108112
}
109113
}
110114

115+
#[inline]
116+
fn foreach_frame<F: Frame<Sample = S>>(&self, mut func: impl FnMut(F)) {
117+
assert_eq!(F::CHANNELS, self.channels);
118+
for f in self.data.chunks_exact(self.channels) {
119+
func(F::from_samples(&mut f.iter().copied()).unwrap());
120+
}
121+
}
122+
111123
#[inline]
112124
fn frames(&self) -> usize {
113125
self.data.len() / self.channels
@@ -137,15 +149,15 @@ impl<'a, T> Samples<'a, T> for Interleaved<'a, T> {
137149
}
138150

139151
/// Struct representing interleaved samples.
140-
pub struct Planar<'a, T> {
141-
data: &'a [&'a [T]],
152+
pub struct Planar<'a, S> {
153+
data: &'a [&'a [S]],
142154
start: usize,
143155
end: usize,
144156
}
145157

146-
impl<'a, T> Planar<'a, T> {
158+
impl<'a, S> Planar<'a, S> {
147159
/// Create a new wrapper around the planar channels and do a sanity check.
148-
pub fn new(data: &'a [&'a [T]]) -> Result<Self, crate::Error> {
160+
pub fn new(data: &'a [&'a [S]]) -> Result<Self, crate::Error> {
149161
if data.is_empty() {
150162
return Err(crate::Error::NoMem);
151163
}
@@ -162,9 +174,9 @@ impl<'a, T> Planar<'a, T> {
162174
}
163175
}
164176

165-
impl<'a, T> Samples<'a, T> for Planar<'a, T> {
177+
impl<'a, S: Sample> Samples<'a, S> for Planar<'a, S> {
166178
#[inline]
167-
fn foreach_sample(&self, channel: usize, mut func: impl FnMut(&'a T)) {
179+
fn foreach_sample(&self, channel: usize, mut func: impl FnMut(&'a S)) {
168180
assert!(channel < self.data.len());
169181

170182
for v in &self.data[channel][self.start..self.end] {
@@ -177,7 +189,7 @@ impl<'a, T> Samples<'a, T> for Planar<'a, T> {
177189
&self,
178190
channel: usize,
179191
iter: impl Iterator<Item = U>,
180-
mut func: impl FnMut(&'a T, U),
192+
mut func: impl FnMut(&'a S, U),
181193
) {
182194
assert!(channel < self.data.len());
183195

@@ -186,6 +198,15 @@ impl<'a, T> Samples<'a, T> for Planar<'a, T> {
186198
}
187199
}
188200

201+
#[inline]
202+
fn foreach_frame<F: Frame<Sample = S>>(&self, mut func: impl FnMut(F)) {
203+
let channels = self.data.len();
204+
assert_eq!(F::CHANNELS, channels);
205+
for f in self.start..self.end {
206+
func(F::from_fn(|c| self.data[c][f]));
207+
}
208+
}
209+
189210
#[inline]
190211
fn frames(&self) -> usize {
191212
self.end - self.start
@@ -261,13 +282,13 @@ pub mod tests {
261282
use dasp_sample::{FromSample, Sample};
262283

263284
#[derive(Clone, Debug)]
264-
pub struct Signal<T: FromSample<f32>> {
265-
pub data: Vec<T>,
285+
pub struct Signal<S: FromSample<f32>> {
286+
pub data: Vec<S>,
266287
pub channels: u32,
267288
pub rate: u32,
268289
}
269290

270-
impl<T: Sample + FromSample<f32> + quickcheck::Arbitrary> quickcheck::Arbitrary for Signal<T> {
291+
impl<S: Sample + FromSample<f32> + quickcheck::Arbitrary> quickcheck::Arbitrary for Signal<S> {
271292
fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
272293
use rand::Rng;
273294

@@ -297,7 +318,7 @@ pub mod tests {
297318
2.0 * std::f32::consts::PI * freqs[3] / rate as f32,
298319
];
299320

300-
let mut data = vec![T::from_sample(0.0f32); num_frames * channels as usize];
321+
let mut data = vec![S::from_sample(0.0f32); num_frames * channels as usize];
301322
for frame in data.chunks_exact_mut(channels as usize) {
302323
let val = max
303324
* (f32::sin(accumulators[0]) * volumes[0]
@@ -307,7 +328,7 @@ pub mod tests {
307328
/ volume_scale;
308329

309330
for sample in frame.iter_mut() {
310-
*sample = T::from_sample(val);
331+
*sample = S::from_sample(val);
311332
}
312333

313334
for (acc, step) in accumulators.iter_mut().zip(steps.iter()) {

0 commit comments

Comments
 (0)