Skip to main content

selene_daemon/player/
opened_decoder.rs

1use std::collections::VecDeque;
2
3use audioadapter_buffers::direct::InterleavedSlice;
4use lunar_lib::trace;
5use rubato::{Fft, FixedSync, Resampler, ResamplerConstructionError};
6use selene_core::decoding::RawDecoder;
7
8use symphonia::core::{
9    errors::Error as SymphoniaError,
10    formats::{SeekMode, SeekTo},
11    units::Time,
12};
13
14use crate::{player::PlayerError, playlist::ResolvedTrack};
15
16pub struct OpenedDecoder {
17    pub decoded_from: ResolvedTrack,
18
19    inner: RawDecoder,
20
21    resampler: Fft<f32>,
22    resample_buffer: VecDeque<f32>,
23
24    pub current_frame: usize,
25
26    pub at_eof: bool,
27}
28
29impl OpenedDecoder {
30    #[must_use]
31    pub fn time(&self) -> f64 {
32        let sample_rate = f64::from(self.inner.stream.codec_params.sample_rate.unwrap());
33        self.current_frame as f64 / sample_rate
34    }
35
36    pub fn decode_next_packet(&mut self) -> Result<VecDeque<f32>, PlayerError> {
37        let channel_count = self.resampler.nbr_channels();
38
39        loop {
40            let next_frame_size = self.resampler.input_frames_next();
41            let Some(packet) = self.inner.decode_next_packet()? else {
42                let mut samples = self.resample_buffer.drain(..).collect::<Vec<_>>();
43
44                let needed_samples = next_frame_size * channel_count;
45                samples.resize(needed_samples, 0.0);
46
47                let buffer_in = InterleavedSlice::new(&samples, channel_count, next_frame_size)
48                    .expect("Sampler buffer contained less capacity then expected");
49
50                let resampled = self.resampler.process(&buffer_in, 0, None).expect(
51                    "Resampler expects input and output to have the same number of channels",
52                );
53
54                self.at_eof = true;
55                return Ok(resampled.take_data().into());
56            };
57
58            self.current_frame += packet.frame_count;
59
60            self.resample_buffer.extend(packet.sample_buf.samples());
61            let mut output = Vec::new();
62
63            while self.resample_buffer.len() >= next_frame_size * channel_count {
64                let samples: Vec<f32> = self
65                    .resample_buffer
66                    .drain(..next_frame_size * channel_count)
67                    .collect();
68
69                let buffer_in = InterleavedSlice::new(&samples, channel_count, next_frame_size)
70                    .expect("Sampler buffer contained less capacity then expected");
71
72                let resampled = self.resampler.process(&buffer_in, 0, None).expect(
73                    "Resampler expects input and output to have the same number of channels",
74                );
75
76                output.extend(resampled.take_data());
77            }
78
79            if !output.is_empty() {
80                return Ok(output.into());
81            }
82        }
83    }
84
85    pub fn seek(&mut self, seconds: f64, increment: bool) -> Result<f64, SymphoniaError> {
86        let seconds = if increment {
87            (self.time() + seconds).max(0.0)
88        } else {
89            seconds
90        };
91
92        let timestamp = Time::from(seconds);
93
94        let seeked_to = self.inner.format_reader.seek(
95            SeekMode::Accurate,
96            SeekTo::Time {
97                time: timestamp,
98                track_id: Some(self.inner.stream.id),
99            },
100        )?;
101
102        self.inner.decoder.reset();
103
104        let time_base = self.inner.stream.codec_params.time_base.unwrap();
105        let raw_time = time_base.calc_time(seeked_to.actual_ts);
106        let time = raw_time.seconds as f64 + raw_time.frac;
107
108        let sample_rate = self.inner.stream.codec_params.sample_rate.unwrap();
109        self.current_frame = (time * f64::from(sample_rate)) as usize;
110
111        Ok(time)
112    }
113}
114
115impl OpenedDecoder {
116    pub fn new(playable: ResolvedTrack, output_sample_rate: usize) -> Result<Self, PlayerError> {
117        let container = playable
118            .track
119            .container()
120            .expect("Engine should handle tracks without containers");
121
122        trace!(
123            "Opening a new decoder from track: '{}'",
124            container.path().display()
125        );
126
127        let inner = RawDecoder::from_container(container, 64 * 1024)?;
128
129        let resampler = new_resampler(
130            inner.stream.codec_params.sample_rate.unwrap() as usize,
131            output_sample_rate,
132            inner.stream.codec_params.channels.unwrap().count(),
133        )?;
134
135        Ok(OpenedDecoder {
136            inner,
137            current_frame: 0,
138            decoded_from: playable,
139            resampler,
140            resample_buffer: VecDeque::with_capacity(1024),
141            at_eof: false,
142        })
143    }
144}
145
146fn new_resampler(
147    input_sample_rate: usize,
148    output_sample_rate: usize,
149    channel_count: usize,
150) -> Result<Fft<f32>, ResamplerConstructionError> {
151    Fft::new(
152        input_sample_rate,
153        output_sample_rate,
154        1024,
155        1,
156        channel_count,
157        FixedSync::Both,
158    )
159}