Get current output frequency and volume from sink/decoder
Is there a way in the lib to get the frequency and volume that is currently being outputted?
I am also trying to get something like this to work. So far, the closest I could get was this:
let s = Decoder::new(file).unwrap()
.periodic_access(Duration::from_millis(40), move |s| {
for amp in s.take(s.channels() as usize) {
tx.try_send(amp);
}
});
Where tx is a SyncSender created like this:
let (tx, rx) = mpsc::sync_channel(8);
This "works" in that I can get some amplitude values out of the stream every 40ms, but since .take consumes the elements in the Source Iterator, it causes audio glitches because I am effectively deleting some samples out of the stream as I go.
I would love to use .peekable() to access some elements of the Iterator without consuming anything, but since the closure in .periodic_access is run repeatedly and .peekable() always calls .next() the first time it runs, it doesn't really help.
Cross reference https://github.com/RustAudio/rodio/issues/238
Same problem here. I created a SpyDecoder POC, encapsulating the decoder and iterator, keeping a bunch of samples from time to time. Seems to work.
pub struct SpyDecoder<R> where R: Read + Seek
{
inner: Decoder<R>,
stats: [i16; 512],
stats_index: usize,
stats_wait: usize,
stats_wait_index: usize,
stats_collect: bool,
}
impl<R> SpyDecoder<R>
where
R: Read + Seek + Send + Sync + 'static,
{
pub fn new(data: R) -> Result<SpyDecoder<R>, DecoderError> {
let inner = Decoder::new(data)?;
Ok(Self {
inner,
stats: [0; 512],
stats_index: 0,
stats_wait: 44000 / 10,
stats_wait_index: 0,
stats_collect: false,
})
}
}
impl<R> Iterator for SpyDecoder<R>
where R: Read + Seek {
type Item = i16;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let sample = self.inner.next();
if self.stats_collect {
if self.stats_index < 512 {
if sample.is_some() {
self.stats[self.stats_index] = sample.unwrap();
self.stats_index += 1;
}
} else {
self.stats_collect = false;
self.stats_index = 0;
// Use the stats (try_send to a channel for stats computation, etc)
}
} else {
if self.stats_wait_index < self.stats_wait {
self.stats_wait_index += 1;
} else {
self.stats_collect = true;
self.stats_wait_index = 0;
}
}
sample
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<R> Source for SpyDecoder<R>
where R: Read + Seek {
fn current_frame_len(&self) -> Option<usize> {
self.inner.current_frame_len()
}
fn channels(&self) -> u16 {
self.inner.channels()
}
fn sample_rate(&self) -> u32 {
self.inner.sample_rate()
}
fn total_duration(&self) -> Option<Duration> {
self.inner.total_duration()
}
}
Same problem here. I created a
SpyDecoderPOC, encapsulating the decoder and iterator, keeping a bunch of samples from time to time. Seems to work.
...
Thank you! This code helped me a lot with my recent project. It really works. With periodic access and a message channel.
As the question seems to have been answered I am gonna close this. Feel free to reopen if you have something related.