Skip to content

Commit 82514bd

Browse files
committed
Only write whole frames to wav
The wav writer returns an error if we do not write a whole frame. This prevents that error by only writing whole frames.
1 parent 082f212 commit 82514bd

File tree

1 file changed

+41
-3
lines changed

1 file changed

+41
-3
lines changed

src/wav_output.rs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::common::assert_error_traits;
22
use crate::Source;
3+
use crate::Sample;
34
use hound::{SampleFormat, WavSpec};
45
use std::io::{self, Write};
56
use std::path;
@@ -29,7 +30,7 @@ assert_error_traits!(ToWavError);
2930
/// # Note
3031
/// This is a convenience wrapper around `wav_to_writer`
3132
pub fn wav_to_file(
32-
source: impl Source,
33+
source: impl Source, // TODO make this take a spanless source
3334
wav_file: impl AsRef<path::Path>,
3435
) -> Result<(), ToWavError> {
3536
let mut file = std::fs::File::create(wav_file)
@@ -58,7 +59,7 @@ pub fn wav_to_file(
5859
/// # Ok::<(), Box<dyn std::error::Error>>(())
5960
/// ```
6061
pub fn wav_to_writer(
61-
source: impl Source,
62+
source: impl Source, // TODO make this take a spanless source
6263
writer: &mut (impl io::Write + io::Seek),
6364
) -> Result<(), ToWavError> {
6465
let format = WavSpec {
@@ -72,12 +73,15 @@ pub fn wav_to_writer(
7273
let mut writer = hound::WavWriter::new(&mut writer, format)
7374
.map_err(Arc::new)
7475
.map_err(ToWavError::Creating)?;
75-
for sample in source {
76+
77+
let whole_frames = WholeFrames::new(source);
78+
for sample in whole_frames {
7679
writer
7780
.write_sample(sample)
7881
.map_err(Arc::new)
7982
.map_err(ToWavError::Writing)?;
8083
}
84+
8185
writer
8286
.finalize()
8387
.map_err(Arc::new)
@@ -90,6 +94,40 @@ pub fn wav_to_writer(
9094
Ok(())
9195
}
9296

97+
struct WholeFrames<I: Iterator<Item=Sample>> {
98+
buffer: Vec<Sample>,
99+
pos: usize,
100+
source: I
101+
}
102+
103+
impl<S: Source> WholeFrames<S> {
104+
fn new(source: S) -> Self {
105+
Self {
106+
buffer: vec![0.0; source.channels().get().into()],
107+
pos: source.channels().get().into(),
108+
source,
109+
}
110+
}
111+
}
112+
113+
impl<I: Iterator<Item = Sample>> Iterator for WholeFrames<I> {
114+
type Item = Sample;
115+
116+
fn next(&mut self) -> Option<Sample> {
117+
if self.pos >= self.buffer.len() {
118+
for sample in &mut self.buffer {
119+
*sample = self.source.next()?;
120+
}
121+
self.pos = 0;
122+
}
123+
124+
let to_yield = self.buffer[self.pos];
125+
self.pos += 1;
126+
Some(to_yield)
127+
}
128+
}
129+
130+
93131
#[cfg(test)]
94132
mod test {
95133
use super::wav_to_file;

0 commit comments

Comments
 (0)