Skip to content

Commit 8ca8cd0

Browse files
authored
fix: prevent channel shift when appending to an empty keep-alive queue (#872)
1 parent 7e9ba6d commit 8ca8cd0

2 files changed

Lines changed: 41 additions & 6 deletions

File tree

src/queue.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ impl Source for SourcesQueueOutput {
141141
_ => {
142142
// - Current source is not exhausted, and is reporting no span length, or
143143
// - Current source is exhausted, and will output silence after it.
144-
self.current.channels().get() as usize
144+
self.channels().get() as usize
145145
}
146146
};
147147

@@ -388,6 +388,26 @@ mod tests {
388388
assert_eq!(rx.sample_rate(), new_sample_rate);
389389
}
390390

391+
#[test]
392+
fn channel_correct_on_first_append() {
393+
let (mixer_tx, mut mixer_rx) = crate::mixer::mixer(nz!(2), nz!(48000));
394+
let (tx, rx) = queue::queue(true);
395+
396+
assert_eq!(rx.channels(), nz!(1), "initial channels should be 1");
397+
mixer_tx.add(rx);
398+
399+
tx.append(SamplesBuffer::new(
400+
nz!(2),
401+
nz!(48000),
402+
vec![1.0, -1.0, 1.0, -1.0],
403+
));
404+
405+
assert_eq!(mixer_rx.next(), Some(1.0), "expected L");
406+
assert_eq!(mixer_rx.next(), Some(-1.0), "expected R");
407+
assert_eq!(mixer_rx.next(), Some(1.0), "expected L");
408+
assert_eq!(mixer_rx.next(), Some(-1.0), "expected R");
409+
}
410+
391411
#[test]
392412
fn append_updates_metadata() {
393413
for keep_alive in [false, true] {

src/source/uniform.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ where
1717
I: Source,
1818
{
1919
inner: Option<ChannelCountConverter<SampleRateConverter<Take<I>>>>,
20+
pending: Option<I>,
2021
target_channels: ChannelCount,
2122
target_sample_rate: SampleRate,
2223
total_duration: Option<Duration>,
@@ -35,10 +36,10 @@ where
3536
target_sample_rate: SampleRate,
3637
) -> UniformSourceIterator<I> {
3738
let total_duration = input.total_duration();
38-
let input = UniformSourceIterator::bootstrap(input, target_channels, target_sample_rate);
3939

4040
UniformSourceIterator {
41-
inner: Some(input),
41+
inner: None,
42+
pending: Some(input),
4243
target_channels,
4344
target_sample_rate,
4445
total_duration,
@@ -75,11 +76,17 @@ where
7576

7677
#[inline]
7778
fn next(&mut self) -> Option<Self::Item> {
78-
if let Some(value) = self.inner.as_mut().unwrap().next() {
79+
if let Some(value) = self.inner.as_mut().and_then(|i| i.next()) {
7980
return Some(value);
8081
}
8182

82-
let input = self.inner.take().unwrap().into_inner().into_inner().iter;
83+
let input = match self.inner.take() {
84+
Some(inner) => inner.into_inner().into_inner().iter,
85+
None => self
86+
.pending
87+
.take()
88+
.expect("pending is Some when inner is None"),
89+
};
8390

8491
let mut input =
8592
UniformSourceIterator::bootstrap(input, self.target_channels, self.target_sample_rate);
@@ -91,7 +98,13 @@ where
9198

9299
#[inline]
93100
fn size_hint(&self) -> (usize, Option<usize>) {
94-
(self.inner.as_ref().unwrap().size_hint().0, None)
101+
let lower = self
102+
.inner
103+
.as_ref()
104+
.map(|i| i.size_hint().0)
105+
.or_else(|| self.pending.as_ref().map(|p| p.size_hint().0))
106+
.unwrap_or(0);
107+
(lower, None)
95108
}
96109
}
97110

@@ -123,6 +136,8 @@ where
123136
fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
124137
if let Some(input) = self.inner.as_mut() {
125138
input.inner_mut().inner_mut().inner_mut().try_seek(pos)
139+
} else if let Some(pending) = self.pending.as_mut() {
140+
pending.try_seek(pos)
126141
} else {
127142
Ok(())
128143
}

0 commit comments

Comments
 (0)