mp3lame_encoder/
input.rs

1use super::{Encoder, ffi};
2
3use core::ptr;
4
5///Type of PCM input for encoder
6///
7///Please note that while you can implement your own trait, it is your responsibility to ensure
8///that `encode` function is correct and safe.
9pub trait EncoderInput {
10    ///Encodes `self` using provided encoder.
11    ///
12    ///## Arguments
13    ///
14    ///- `output_buf` - is guaranteed to never to be `null`;
15    ///- `output_len` - is guaranteed to be capacity of memory pointed by `output_buf`.
16    ///
17    ///## Returns
18    ///
19    ///Zero or positive integer to indicate success and number of bytes written.
20    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int;
21}
22
23///PCM data with only 1 channel
24///
25///In this case, number of samples is always equals to number of samples in slice.
26pub struct MonoPcm<'a, T>(pub &'a [T]);
27
28impl EncoderInput for MonoPcm<'_, u16> {
29    #[inline(always)]
30    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
31        unsafe {
32            ffi::lame_encode_buffer(encoder.ptr(), self.0.as_ptr() as _, ptr::null(), self.0.len() as _, output_buf as _, output_len as _)
33        }
34    }
35}
36
37impl EncoderInput for MonoPcm<'_, i16> {
38    #[inline(always)]
39    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
40        unsafe {
41            ffi::lame_encode_buffer(encoder.ptr(), self.0.as_ptr(), ptr::null(), self.0.len() as _, output_buf as _, output_len as _)
42        }
43    }
44}
45
46//On most platforms it should be i32
47impl EncoderInput for MonoPcm<'_, libc::c_int> {
48    #[inline(always)]
49    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
50        unsafe {
51            ffi::lame_encode_buffer_int(encoder.ptr(), self.0.as_ptr(), ptr::null(), self.0.len() as _, output_buf as _, output_len as _)
52        }
53    }
54}
55
56#[cfg(all(unix, all(not(target_arch = "x86"), not(target_arch = "arm"))))]
57//On most unix it should be i64.
58//But unclear about other platforms, so it is only implemented there as otherwise it is i32.
59impl EncoderInput for MonoPcm<'_, libc::c_long> {
60    #[inline(always)]
61    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
62        unsafe {
63            ffi::lame_encode_buffer_long2(encoder.ptr(), self.0.as_ptr(), ptr::null(), self.0.len() as _, output_buf as _, output_len as _)
64        }
65    }
66}
67
68impl EncoderInput for MonoPcm<'_, f32> {
69    #[inline(always)]
70    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
71        unsafe {
72            ffi::lame_encode_buffer_ieee_float(encoder.ptr(), self.0.as_ptr(), ptr::null(), self.0.len() as _, output_buf as _, output_len as _)
73        }
74    }
75}
76
77impl EncoderInput for MonoPcm<'_, f64> {
78    #[inline(always)]
79    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
80        unsafe {
81            ffi::lame_encode_buffer_ieee_double(encoder.ptr(), self.0.as_ptr(), ptr::null(), self.0.len() as _, output_buf as _, output_len as _)
82        }
83    }
84}
85
86///PCM data represented by two channels.
87///
88///Number of samples must be equal between left and right channels.
89///
90///If you want to feed encoder single PCM data, then use [MonoPcm](MonoPcm)
91///In case length of channels is not equal, it will always feed encoder minimum of both length.
92///In debug mode it will panic in this case also to warn you of error.
93pub struct DualPcm<'a, T> {
94    ///left channel PCM data
95    pub left: &'a [T],
96    ///right channel PCM data
97    pub right: &'a [T],
98}
99
100impl EncoderInput for DualPcm<'_, i16> {
101    #[inline(always)]
102    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
103        debug_assert_eq!(self.left.len(), self.right.len());
104        let samples_num = core::cmp::min(self.left.len(), self.right.len());
105        unsafe {
106            ffi::lame_encode_buffer(encoder.ptr(), self.left.as_ptr(), self.right.as_ptr(), samples_num as _, output_buf as _, output_len as _)
107        }
108    }
109}
110
111impl EncoderInput for DualPcm<'_, u16> {
112    #[inline(always)]
113    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
114        debug_assert_eq!(self.left.len(), self.right.len());
115        let samples_num = core::cmp::min(self.left.len(), self.right.len());
116        unsafe {
117            ffi::lame_encode_buffer(encoder.ptr(), self.left.as_ptr() as _, self.right.as_ptr() as _, samples_num as _, output_buf as _, output_len as _)
118        }
119    }
120}
121
122impl EncoderInput for DualPcm<'_, libc::c_int> {
123    #[inline(always)]
124    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
125        debug_assert_eq!(self.left.len(), self.right.len());
126        let samples_num = core::cmp::min(self.left.len(), self.right.len());
127        unsafe {
128            ffi::lame_encode_buffer_int(encoder.ptr(), self.left.as_ptr(), self.right.as_ptr(), samples_num as _, output_buf as _, output_len as _)
129        }
130    }
131}
132
133impl EncoderInput for DualPcm<'_, f32> {
134    #[inline(always)]
135    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
136        debug_assert_eq!(self.left.len(), self.right.len());
137        let samples_num = core::cmp::min(self.left.len(), self.right.len());
138        unsafe {
139            ffi::lame_encode_buffer_ieee_float(encoder.ptr(), self.left.as_ptr() as _, self.right.as_ptr() as _, samples_num as _, output_buf as _, output_len as _)
140        }
141    }
142}
143
144impl EncoderInput for DualPcm<'_, f64> {
145    #[inline(always)]
146    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
147        debug_assert_eq!(self.left.len(), self.right.len());
148        let samples_num = core::cmp::min(self.left.len(), self.right.len());
149        unsafe {
150            ffi::lame_encode_buffer_ieee_double(encoder.ptr(), self.left.as_ptr() as _, self.right.as_ptr() as _, samples_num as _, output_buf as _, output_len as _)
151        }
152    }
153}
154
155///PCM data in interleaved form
156///
157///Interleaved input assumes you have two channels encoded within continuous buffer as sequence pairs: `[<left>, <right>...]`
158///Hence, number of samples is always `data.len() / 2`.
159///
160///If it is not your case, encoding will panic in debug mode, but otherwise you most likely to get incomplete output.
161pub struct InterleavedPcm<'a, T>(pub &'a [T]);
162
163impl EncoderInput for InterleavedPcm<'_, i16> {
164    #[inline(always)]
165    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
166        let samples_num = self.0.len() / 2;
167        debug_assert_eq!(self.0.len() % 2, 0);
168        //lame_encode_buffer_interleaved() signature takes mutable pointer, but all other functions const*, wtf?
169        unsafe {
170            ffi::lame_encode_buffer_interleaved(encoder.ptr(), self.0.as_ptr() as _, samples_num as _, output_buf as _, output_len as _)
171        }
172    }
173}
174
175impl EncoderInput for InterleavedPcm<'_, u16> {
176    #[inline(always)]
177    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
178        let samples_num = self.0.len() / 2;
179        debug_assert_eq!(self.0.len() % 2, 0);
180        //lame_encode_buffer_interleaved() signature takes mutable pointer, but all other functions const*, wtf?
181        unsafe {
182            ffi::lame_encode_buffer_interleaved(encoder.ptr(), self.0.as_ptr() as _, samples_num as _, output_buf as _, output_len as _)
183        }
184    }
185}
186
187impl EncoderInput for InterleavedPcm<'_, libc::c_int> {
188    #[inline(always)]
189    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
190        let samples_num = self.0.len() / 2;
191        debug_assert_eq!(self.0.len() % 2, 0);
192        unsafe {
193            ffi::lame_encode_buffer_interleaved_int(encoder.ptr(), self.0.as_ptr(), samples_num as _, output_buf as _, output_len as _)
194        }
195    }
196}
197
198impl EncoderInput for InterleavedPcm<'_, f32> {
199    #[inline(always)]
200    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
201        let samples_num = self.0.len() / 2;
202        debug_assert_eq!(self.0.len() % 2, 0);
203        unsafe {
204            ffi::lame_encode_buffer_interleaved_ieee_float(encoder.ptr(), self.0.as_ptr(), samples_num as _, output_buf as _, output_len as _)
205        }
206    }
207}
208
209impl EncoderInput for InterleavedPcm<'_, f64> {
210    #[inline(always)]
211    fn encode(self, encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
212        let samples_num = self.0.len() / 2;
213        debug_assert_eq!(self.0.len() % 2, 0);
214        unsafe {
215            ffi::lame_encode_buffer_interleaved_ieee_double(encoder.ptr(), self.0.as_ptr(), samples_num as _, output_buf as _, output_len as _)
216        }
217    }
218}
219
220///Flush method.
221pub trait EncoderFlush {
222    ///Performs flush, returning result as signed integer.
223    ///
224    ///## Arguments
225    ///
226    ///- `output_buf` - is guaranteed to never to be `null`;
227    ///- `output_len` - is guaranteed to be capacity of memory pointed by `output_buf`.
228    ///
229    ///## Returns
230    ///
231    ///Zero or positive integer to indicate success and number of bytes written.
232    fn flush(encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int;
233}
234
235///Performs flush, padding gaps with 0
236pub struct FlushGap;
237
238impl EncoderFlush for FlushGap {
239    #[allow(clippy::not_unsafe_ptr_arg_deref)]
240    #[inline(always)]
241    fn flush(encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
242        unsafe {
243            ffi::lame_encode_flush(encoder.ptr(), output_buf, output_len as _)
244        }
245    }
246}
247
248///Performs flush, padding it with ancillary data
249pub struct FlushNoGap;
250
251impl EncoderFlush for FlushNoGap {
252    #[allow(clippy::not_unsafe_ptr_arg_deref)]
253    #[inline(always)]
254    fn flush(encoder: &mut Encoder, output_buf: *mut u8, output_len: usize) -> libc::c_int {
255        unsafe {
256            ffi::lame_encode_flush_nogap(encoder.ptr(), output_buf, output_len as _)
257        }
258    }
259}