Merge branch 'master' into seek_runtime_err

This commit is contained in:
dvdsk 2024-04-06 12:00:17 +02:00
commit 6f1f44f04a
No known key found for this signature in database
GPG key ID: 6CF9D20C5709A836
15 changed files with 99 additions and 61 deletions

View file

@ -43,12 +43,8 @@ jobs:
# Don't use a 'components:' entry--we don't need them with beta/nightly, plus nightly often doesn't have them
override: true
# This block can be uncommented to add clippy to CI, but first the existing clippy warnings need to be fixed!
# - name: clippy
# run: |
# rustup component add clippy
# cargo clippy -- -D warnings
# if: matrix.toolchain == 'stable' && matrix.os == 'ubuntu-latest'
- run: cargo clippy -- -D warnings
if: matrix.toolchain == 'stable' && matrix.os == 'ubuntu-latest'
- run: |
rustup component add rustfmt

View file

@ -28,6 +28,7 @@ wav = ["hound"]
mp3 = ["symphonia-mp3"]
minimp3 = ["dep:minimp3_fixed"]
wasm-bindgen = ["cpal/wasm-bindgen"]
cpal-shared-stdcxx = ["cpal/oboe-shared-stdcxx"]
symphonia-aac = ["symphonia/aac"]
symphonia-all = ["symphonia-aac", "symphonia-flac", "symphonia-isomp4", "symphonia-mp3", "symphonia-vorbis", "symphonia-wav"]
symphonia-flac = ["symphonia/flac"]

View file

@ -1,3 +1,5 @@
use cpal::Sample;
/// Iterator that converts from a certain channel count to another.
#[derive(Clone, Debug)]
pub struct ChannelCountConverter<I>
@ -19,7 +21,7 @@ where
///
/// # Panic
///
/// Panicks if `from` or `to` are equal to 0.
/// Panics if `from` or `to` are equal to 0.
///
#[inline]
pub fn new(
@ -55,25 +57,29 @@ where
impl<I> Iterator for ChannelCountConverter<I>
where
I: Iterator,
I::Item: Clone,
I::Item: Sample,
{
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
let result = if self.next_output_sample_pos == self.from - 1 {
let value = self.input.next();
self.sample_repeat = value.clone();
value
} else if self.next_output_sample_pos < self.from {
self.input.next()
} else {
self.sample_repeat.clone()
let result = match self.next_output_sample_pos {
0 => {
// save first sample for mono -> stereo conversion
let value = self.input.next();
self.sample_repeat = value;
value
}
x if x < self.from => self.input.next(),
1 => self.sample_repeat,
_ => Some(I::Item::EQUILIBRIUM),
};
self.next_output_sample_pos += 1;
if result.is_some() {
self.next_output_sample_pos += 1;
}
if self.next_output_sample_pos == self.to {
self.next_output_sample_pos -= self.to;
self.next_output_sample_pos = 0;
if self.from > self.to {
for _ in self.to..self.from {
@ -89,11 +95,14 @@ where
fn size_hint(&self) -> (usize, Option<usize>) {
let (min, max) = self.input.size_hint();
let min =
(min / self.from as usize) * self.to as usize + self.next_output_sample_pos as usize;
let max = max.map(|max| {
(max / self.from as usize) * self.to as usize + self.next_output_sample_pos as usize
});
let consumed = std::cmp::min(self.from, self.next_output_sample_pos) as usize;
let calculate = |size| {
(size + consumed) / self.from as usize * self.to as usize
- self.next_output_sample_pos as usize
};
let min = calculate(min);
let max = max.map(calculate);
(min, max)
}
@ -102,7 +111,7 @@ where
impl<I> ExactSizeIterator for ChannelCountConverter<I>
where
I: ExactSizeIterator,
I::Item: Clone,
I::Item: Sample,
{
}
@ -112,36 +121,60 @@ mod test {
#[test]
fn remove_channels() {
let input = vec![1u16, 2, 3, 1, 2, 3];
let input = vec![1u16, 2, 3, 4, 5, 6];
let output = ChannelCountConverter::new(input.into_iter(), 3, 2).collect::<Vec<_>>();
assert_eq!(output, [1, 2, 1, 2]);
assert_eq!(output, [1, 2, 4, 5]);
let input = vec![1u16, 2, 3, 4, 1, 2, 3, 4];
let input = vec![1u16, 2, 3, 4, 5, 6, 7, 8];
let output = ChannelCountConverter::new(input.into_iter(), 4, 1).collect::<Vec<_>>();
assert_eq!(output, [1, 1]);
assert_eq!(output, [1, 5]);
}
#[test]
fn add_channels() {
let input = vec![1u16, 2, 1, 2];
let output = ChannelCountConverter::new(input.into_iter(), 2, 3).collect::<Vec<_>>();
assert_eq!(output, [1, 2, 2, 1, 2, 2]);
let input = vec![1i16, 2, 3, 4];
let output = ChannelCountConverter::new(input.into_iter(), 1, 2).collect::<Vec<_>>();
assert_eq!(output, [1, 1, 2, 2, 3, 3, 4, 4]);
let input = vec![1u16, 2, 1, 2];
let input = vec![1i16, 2];
let output = ChannelCountConverter::new(input.into_iter(), 1, 4).collect::<Vec<_>>();
assert_eq!(output, [1, 1, 0, 0, 2, 2, 0, 0]);
let input = vec![1i16, 2, 3, 4];
let output = ChannelCountConverter::new(input.into_iter(), 2, 4).collect::<Vec<_>>();
assert_eq!(output, [1, 2, 2, 2, 1, 2, 2, 2]);
assert_eq!(output, [1, 2, 0, 0, 3, 4, 0, 0]);
}
#[test]
fn size_hint() {
fn test(input: &[i16], from: cpal::ChannelCount, to: cpal::ChannelCount) {
let mut converter = ChannelCountConverter::new(input.iter().copied(), from, to);
let count = converter.clone().count();
for left_in_iter in (0..=count).rev() {
println!("left_in_iter = {}", left_in_iter);
assert_eq!(converter.size_hint(), (left_in_iter, Some(left_in_iter)));
converter.next();
}
assert_eq!(converter.size_hint(), (0, Some(0)));
}
test(&[1i16, 2, 3], 1, 2);
test(&[1i16, 2, 3, 4], 2, 4);
test(&[1i16, 2, 3, 4], 4, 2);
test(&[1i16, 2, 3, 4, 5, 6], 3, 8);
test(&[1i16, 2, 3, 4, 5, 6, 7, 8], 4, 1);
}
#[test]
fn len_more() {
let input = vec![1u16, 2, 1, 2];
let input = vec![1i16, 2, 3, 4];
let output = ChannelCountConverter::new(input.into_iter(), 2, 3);
assert_eq!(output.len(), 6);
}
#[test]
fn len_less() {
let input = vec![1u16, 2, 1, 2];
let input = vec![1i16, 2, 3, 4];
let output = ChannelCountConverter::new(input.into_iter(), 2, 1);
assert_eq!(output.len(), 2);
}

View file

@ -110,12 +110,12 @@ where
Ordering::Equal => raw_val as i16,
Ordering::Greater => (raw_val >> (self.bits_per_sample - 16)) as i16,
};
return Some(real_val as i16);
return Some(real_val);
}
// Load the next block.
self.current_block_off = 0;
let buffer = mem::replace(&mut self.current_block, Vec::new());
let buffer = mem::take(&mut self.current_block);
match self.reader.blocks().read_next_or_eof(buffer) {
Ok(Some(block)) => {
self.current_block_channel_len = (block.len() / block.channels()) as usize;
@ -132,7 +132,7 @@ fn is_flac<R>(mut data: R) -> bool
where
R: Read + Seek,
{
let stream_pos = data.seek(SeekFrom::Current(0)).unwrap();
let stream_pos = data.stream_position().unwrap();
if FlacReader::new(data.by_ref()).is_err() {
data.seek(SeekFrom::Start(stream_pos)).unwrap();

View file

@ -4,7 +4,6 @@ use std::error::Error;
use std::fmt;
#[allow(unused_imports)]
use std::io::{Read, Seek, SeekFrom};
use std::marker::Sync;
use std::mem;
use std::str::FromStr;
use std::time::Duration;
@ -41,6 +40,9 @@ pub struct LoopedDecoder<R>(DecoderImpl<R>)
where
R: Read + Seek;
// can not really reduce the size of the VorbisDecoder. There are not any
// arrays just a lot of struct fields.
#[allow(clippy::large_enum_variant)]
enum DecoderImpl<R>
where
R: Read + Seek,
@ -231,9 +233,7 @@ where
match symphonia::SymphoniaDecoder::new(mss, None) {
Err(e) => Err(e),
Ok(decoder) => {
return Ok(Decoder(DecoderImpl::Symphonia(decoder)));
}
Ok(decoder) => Ok(Decoder(DecoderImpl::Symphonia(decoder))),
}
}
#[cfg(not(feature = "symphonia"))]
@ -324,9 +324,7 @@ where
match symphonia::SymphoniaDecoder::new(mss, Some(hint)) {
Err(e) => Err(e),
Ok(decoder) => {
return Ok(Decoder(DecoderImpl::Symphonia(decoder)));
}
Ok(decoder) => Ok(Decoder(DecoderImpl::Symphonia(decoder))),
}
}
}
@ -479,7 +477,7 @@ where
}
#[cfg(feature = "symphonia")]
DecoderImpl::Symphonia(source) => {
let mut reader = Box::new(source).into_inner();
let mut reader = source.into_inner();
reader.seek(SeekFrom::Start(0)).ok()?;
let mut source = symphonia::SymphoniaDecoder::new(reader, None).ok()?;
let sample = source.next();

View file

@ -1,5 +1,4 @@
use std::io::{Read, Result, Seek, SeekFrom};
use std::marker::Sync;
use symphonia::core::io::MediaSource;

View file

@ -49,7 +49,7 @@ impl SymphoniaDecoder {
}
}
pub(crate) fn into_inner(self: Box<Self>) -> MediaSourceStream {
pub(crate) fn into_inner(self) -> MediaSourceStream {
self.format.into_inner()
}
@ -106,23 +106,22 @@ impl SymphoniaDecoder {
};
let spec = decoded.spec().to_owned();
let buffer = SymphoniaDecoder::get_buffer(decoded, &spec);
return Ok(Some(SymphoniaDecoder {
Ok(Some(SymphoniaDecoder {
decoder,
current_frame_offset: 0,
format: probed.format,
total_duration,
buffer,
spec,
}));
}))
}
#[inline]
fn get_buffer(decoded: AudioBufferRef, spec: &SignalSpec) -> SampleBuffer<i16> {
let duration = units::Duration::from(decoded.capacity() as u64);
let mut buffer = SampleBuffer::<i16>::new(duration, spec.clone());
let mut buffer = SampleBuffer::<i16>::new(duration, *spec);
buffer.copy_interleaved_ref(decoded);
return buffer;
buffer
}
}

View file

@ -132,7 +132,7 @@ fn is_vorbis<R>(mut data: R) -> bool
where
R: Read + Seek,
{
let stream_pos = data.seek(SeekFrom::Current(0)).unwrap();
let stream_pos = data.stream_position().unwrap();
if OggStreamReader::new(data.by_ref()).is_err() {
data.seek(SeekFrom::Start(stream_pos)).unwrap();

View file

@ -179,7 +179,7 @@ fn is_wave<R>(mut data: R) -> bool
where
R: Read + Seek,
{
let stream_pos = data.seek(SeekFrom::Current(0)).unwrap();
let stream_pos = data.stream_position().unwrap();
if WavReader::new(data.by_ref()).is_err() {
data.seek(SeekFrom::Start(stream_pos)).unwrap();

View file

@ -43,9 +43,12 @@ where
// TODO: consider reimplementing this with `from_factory`
type Sound<S> = Box<dyn Source<Item = S> + Send>;
type SignalDone = Option<Sender<()>>;
/// The input of the queue.
pub struct SourcesQueueInput<S> {
next_sounds: Mutex<Vec<(Box<dyn Source<Item = S> + Send>, Option<Sender<()>>)>>,
next_sounds: Mutex<Vec<(Sound<S>, SignalDone)>>,
// See constructor.
keep_alive_if_empty: AtomicBool,

View file

@ -131,7 +131,7 @@ impl Sink {
{
let mut to_clear = controls.to_clear.lock().unwrap();
if *to_clear > 0 {
let _ = src.inner_mut().skip();
src.inner_mut().skip();
*to_clear -= 1;
}
}
@ -298,6 +298,7 @@ impl Sink {
}
/// Returns the number of sounds currently in the queue.
#[allow(clippy::len_without_is_empty)]
#[inline]
pub fn len(&self) -> usize {
self.sound_count.load(Ordering::Relaxed)

View file

@ -50,7 +50,7 @@ where
return;
}
skip_samples(input, frame_len as usize);
skip_samples(input, frame_len);
duration -= Duration::from_nanos((frame_len * ns_per_sample as usize) as u64);
}

View file

@ -122,7 +122,7 @@ where
None
} else if let Some(sample) = self.input.next() {
let sample = match &self.filter {
Some(filter) => filter.apply(sample, &self),
Some(filter) => filter.apply(sample, self),
None => sample,
};

View file

@ -135,6 +135,14 @@ impl SpatialSink {
self.sink.is_paused()
}
/// Removes all currently loaded `Source`s from the `SpatialSink` and pauses it.
///
/// See `pause()` for information about pausing a `Sink`.
#[inline]
pub fn clear(&self) {
self.sink.clear();
}
/// Stops the sink by emptying the queue.
#[inline]
pub fn stop(&self) {
@ -160,6 +168,7 @@ impl SpatialSink {
}
/// Returns the number of sounds currently in the queue.
#[allow(clippy::len_without_is_empty)]
#[inline]
pub fn len(&self) -> usize {
self.sink.len()

View file

@ -1,5 +1,4 @@
use std::io::{Read, Seek};
use std::marker::Sync;
use std::sync::{Arc, Weak};
use std::{error, fmt};
@ -353,7 +352,7 @@ fn supported_output_formats(
if HZ_44100 < max_rate && HZ_44100 > min_rate {
formats.push(sf.clone().with_sample_rate(HZ_44100))
}
formats.push(sf.with_sample_rate(min_rate));
formats.push(sf.clone().with_sample_rate(min_rate));
formats
}))
}