falcon_ffmpeg/
audio_file.rs1use std::path::Path;
6
7use crate::decode::{Decoder, Input, OUT_CHANNELS, OUT_RATE, Packet, Resampler};
8use crate::{Error, Result, ffi};
9
10pub struct AudioFile {
12 input: Input,
13 decoder: Decoder,
14 resampler: Resampler,
15 packet: Packet,
16 buf: Vec<f32>,
17 pos: usize,
18 skip_to: Option<f64>,
20 drained: bool,
21 duration: f64,
22 position: f64,
24}
25
26impl AudioFile {
27 pub const CHANNELS: u16 = OUT_CHANNELS as u16;
28 pub const RATE: u32 = OUT_RATE;
29
30 pub fn open(path: &Path) -> Result<AudioFile> {
31 let input = Input::open(path)?;
32 let (index, codec) = input.best(ffi::AVMEDIA_TYPE_AUDIO).ok_or_else(|| Error("no sound FFmpeg can decode".into()))?;
33 let decoder = Decoder::open(&input, index, codec)?;
34 let duration = input.duration(Some(index));
35 let (resampler, packet) = (Resampler::new(input.api()), Packet::new(input.api())?);
36 Ok(AudioFile { input, decoder, resampler, packet, buf: Vec::new(), pos: 0, skip_to: None, drained: false, duration, position: 0.0 })
37 }
38
39 pub fn duration(&self) -> f64 {
41 self.duration
42 }
43
44 pub fn position(&self) -> f64 {
46 self.position
47 }
48
49 pub fn next_sample(&mut self) -> Option<f32> {
51 while self.pos >= self.buf.len() {
52 if !self.fill() {
53 return None;
54 }
55 }
56 let s = self.buf[self.pos];
57 self.pos += 1;
58 if self.pos.is_multiple_of(OUT_CHANNELS) {
59 self.position += 1.0 / f64::from(OUT_RATE);
60 }
61 Some(s)
62 }
63
64 pub fn next_block(&mut self) -> Option<&[f32]> {
67 if self.pos >= self.buf.len() && !self.fill() {
68 return None;
69 }
70 let block = &self.buf[self.pos..];
71 self.position += (block.len() / OUT_CHANNELS) as f64 / f64::from(OUT_RATE);
72 self.pos = self.buf.len();
73 Some(block)
74 }
75
76 pub fn seek(&mut self, secs: f64) -> Result<()> {
78 self.input.seek(secs)?;
79 self.decoder.flush();
80 self.resampler.reset();
81 self.buf.clear();
82 self.pos = 0;
83 self.skip_to = Some(secs.max(0.0));
84 self.drained = false;
85 self.position = secs.max(0.0);
86 Ok(())
87 }
88
89 fn fill(&mut self) -> bool {
91 self.buf.clear();
92 self.pos = 0;
93 let index = self.decoder.info.index;
94 while self.buf.is_empty() {
95 if self.drained {
96 return false;
97 }
98 self.packet.unref();
99 match self.input.read(&mut self.packet) {
100 Ok(true) if self.packet.stream_index() != index => continue,
101 Ok(true) => {
102 let _ = self.decoder.send(Some(&self.packet));
103 }
104 _ => {
105 let _ = self.decoder.send(None);
106 self.drained = true;
107 }
108 }
109 while self.decoder.receive() {
110 let f = self.decoder.frame();
111 let pts = self.decoder.pts(f);
112 let Ok(mut samples) = self.resampler.convert(f, 1.0) else { continue };
113 if let (Some(target), Some(t)) = (self.skip_to, pts) {
114 if t < target {
115 let skip = (((target - t) * f64::from(OUT_RATE)) as usize * OUT_CHANNELS).min(samples.len());
116 samples.drain(..skip);
117 }
118 if !samples.is_empty() {
119 self.skip_to = None;
120 }
121 }
122 self.buf.extend_from_slice(&samples);
123 }
124 }
125 true
126 }
127}