minimp3_fixed/
lib.rs

1//! # minimp3
2//!
3//! Provides a simple wrapper and bindinings to the [minimp3](https://github.com/lieff/minimp3) C library.
4//!
5//! ## Tokio
6//!
7//! By enabling the feature flag `async_tokio` you can decode frames using async
8//! IO and tokio.
9//!
10//! [See the README for example usages.](https://github.com/germangb/minimp3-rs/tree/async)
11pub use error::Error;
12pub use minimp3_sys as ffi;
13
14use slice_ring_buffer::SliceRingBuffer;
15use std::{io, marker::Send, mem};
16
17mod error;
18
19/// Maximum number of samples present in a MP3 frame.
20pub const MAX_SAMPLES_PER_FRAME: usize = ffi::MINIMP3_MAX_SAMPLES_PER_FRAME as usize;
21
22const BUFFER_SIZE: usize = MAX_SAMPLES_PER_FRAME * 15;
23const REFILL_TRIGGER: usize = MAX_SAMPLES_PER_FRAME * 8;
24
25/// A MP3 decoder which consumes a reader and produces [`Frame`]s.
26///
27/// [`Frame`]: ./struct.Frame.html
28pub struct Decoder<R> {
29    reader: R,
30    buffer: SliceRingBuffer<u8>,
31    buffer_refill: Box<[u8; MAX_SAMPLES_PER_FRAME * 5]>,
32    decoder: Box<ffi::mp3dec_t>,
33}
34
35// Explicitly impl [Send] for [Decoder]s. This isn't a great idea and should
36// probably be removed in the future. The only reason it's here is that
37// [SliceRingBuffer] doesn't implement [Send] (since it uses raw pointers
38// internally), even though it's safe to send it across thread boundaries.
39unsafe impl<R: Send> Send for Decoder<R> {}
40
41/// A MP3 frame, owning the decoded audio of that frame.
42#[derive(Debug, Clone)]
43pub struct Frame {
44    /// The decoded audio held by this frame. Channels are interleaved.
45    pub data: Vec<i16>,
46    /// This frame's sample rate in hertz.
47    pub sample_rate: i32,
48    /// The number of channels in this frame.
49    pub channels: usize,
50    /// MPEG layer used by this file.
51    pub layer: usize,
52    /// Current bitrate as of this frame, in kb/s.
53    pub bitrate: i32,
54}
55
56impl<R> Decoder<R> {
57    /// Creates a new decoder, consuming the `reader`.
58    pub fn new(reader: R) -> Self {
59        let mut minidec = unsafe { Box::new(mem::zeroed()) };
60        unsafe { ffi::mp3dec_init(&mut *minidec) }
61
62        Self {
63            reader,
64            buffer: SliceRingBuffer::with_capacity(BUFFER_SIZE),
65            buffer_refill: Box::new([0; MAX_SAMPLES_PER_FRAME * 5]),
66            decoder: minidec,
67        }
68    }
69
70    /// Return a reference to the underlying reader.
71    pub fn reader(&self) -> &R {
72        &self.reader
73    }
74
75    /// Return a mutable reference to the underlying reader (reading from it is
76    /// not recommended).
77    pub fn reader_mut(&mut self) -> &mut R {
78        &mut self.reader
79    }
80
81    /// Destroy the decoder and return the inner reader
82    pub fn into_inner(self) -> R {
83        self.reader
84    }
85
86    fn decode_frame(&mut self) -> Result<Frame, Error> {
87        let mut frame_info = unsafe { mem::zeroed() };
88        let mut pcm = Vec::with_capacity(MAX_SAMPLES_PER_FRAME);
89        let samples: usize = unsafe {
90            ffi::mp3dec_decode_frame(
91                &mut *self.decoder,
92                self.buffer.as_ptr(),
93                self.buffer.len() as _,
94                pcm.as_mut_ptr(),
95                &mut frame_info,
96            ) as _
97        };
98
99        if samples > 0 {
100            unsafe {
101                pcm.set_len(samples * frame_info.channels as usize);
102            }
103        }
104
105        let frame = Frame {
106            data: pcm,
107            sample_rate: frame_info.hz,
108            channels: frame_info.channels as usize,
109            layer: frame_info.layer as usize,
110            bitrate: frame_info.bitrate_kbps,
111        };
112
113        let current_len = self.buffer.len();
114        self.buffer
115            .truncate_front(current_len - frame_info.frame_bytes as usize);
116
117        if samples == 0 {
118            if frame_info.frame_bytes > 0 {
119                Err(Error::SkippedData)
120            } else {
121                Err(Error::InsufficientData)
122            }
123        } else {
124            Ok(frame)
125        }
126    }
127}
128
129#[cfg(feature = "async_tokio")]
130impl<R: tokio::io::AsyncRead + std::marker::Unpin> Decoder<R> {
131    /// Reads a new frame from the internal reader. Returns a [`Frame`](Frame)
132    /// if one was found, or, otherwise, an `Err` explaining why not.
133    pub async fn next_frame_future(&mut self) -> Result<Frame, Error> {
134        loop {
135            // Keep our buffers full
136            let bytes_read = if self.buffer.len() < REFILL_TRIGGER {
137                Some(self.refill_future().await?)
138            } else {
139                None
140            };
141
142            match self.decode_frame() {
143                Ok(frame) => return Ok(frame),
144                // Don't do anything if we didn't have enough data or we skipped data,
145                // just let the loop spin around another time.
146                Err(Error::InsufficientData) | Err(Error::SkippedData) => {
147                    // If there are no more bytes to be read from the file, return EOF
148                    if let Some(0) = bytes_read {
149                        return Err(Error::Eof);
150                    }
151                }
152                Err(e) => return Err(e),
153            }
154        }
155    }
156
157    async fn refill_future(&mut self) -> Result<usize, io::Error> {
158        use tokio::io::AsyncReadExt;
159
160        let read_bytes = self.reader.read(&mut self.buffer_refill[..]).await?;
161        self.buffer.extend(self.buffer_refill[..read_bytes].iter());
162
163        Ok(read_bytes)
164    }
165}
166
167// TODO FIXME do something about the code repetition. The only difference is the
168//  use of .await after IO reads...
169
170impl<R: io::Read> Decoder<R> {
171    /// Reads a new frame from the internal reader. Returns a [`Frame`](Frame)
172    /// if one was found, or, otherwise, an `Err` explaining why not.
173    pub fn next_frame(&mut self) -> Result<Frame, Error> {
174        loop {
175            // Keep our buffers full
176            let bytes_read = if self.buffer.len() < REFILL_TRIGGER {
177                Some(self.refill()?)
178            } else {
179                None
180            };
181
182            match self.decode_frame() {
183                Ok(frame) => return Ok(frame),
184                // Don't do anything if we didn't have enough data or we skipped data,
185                // just let the loop spin around another time.
186                Err(Error::InsufficientData) | Err(Error::SkippedData) => {
187                    // If there are no more bytes to be read from the file, return EOF
188                    if let Some(0) = bytes_read {
189                        return Err(Error::Eof);
190                    }
191                }
192                Err(e) => return Err(e),
193            }
194        }
195    }
196
197    fn refill(&mut self) -> Result<usize, io::Error> {
198        let read_bytes = self.reader.read(&mut self.buffer_refill[..])?;
199        self.buffer.extend(self.buffer_refill[..read_bytes].iter());
200
201        Ok(read_bytes)
202    }
203}