mp3lame_encoder/
lib.rs

1//!High level wrapper over [mp3lame-sys](https://crates.io/crates/mp3lame-sys)
2//!
3//!## Example
4//!
5//!```rust
6//!use mp3lame_encoder::{Builder, Id3Tag, DualPcm, FlushNoGap};
7//!
8//!let id3tag = Id3Tag {
9//!    title: b"My title",
10//!    artist: &[],
11//!    album: b"My album",
12//!    album_art: &[],
13//!    year: b"Current year",
14//!    comment: b"Just my comment",
15//!};
16//!
17//!//Create codec using builder
18//!let mut mp3_encoder = Builder::new().expect("Create LAME builder");
19//!mp3_encoder.set_num_channels(2).expect("set channels");
20//!mp3_encoder.set_sample_rate(44_100).expect("set sample rate");
21//!mp3_encoder.set_brate(mp3lame_encoder::Bitrate::Kbps192).expect("set brate");
22//!mp3_encoder.set_quality(mp3lame_encoder::Quality::Best).expect("set quality");
23//!mp3_encoder.set_id3_tag(id3tag);
24//!let mut mp3_encoder = mp3_encoder.build().expect("To initialize LAME encoder");
25//! 
26//!//Methods prefixed with `with_*` return Self for convenience
27//!let mut mp3_encoder = Builder::new().expect("Create LAME builder")
28//!    .with_num_channels(2).expect("set channels")
29//!    .with_sample_rate(44_100).expect("set sample rate")
30//!    .with_brate(mp3lame_encoder::Bitrate::Kbps192).expect("set brate")
31//!    .with_quality(mp3lame_encoder::Quality::Best).expect("set quality")
32//!    .with_id3_tag(id3tag).expect("set tags")
33//!    .build().expect("To initialize LAME encoder");
34//!
35//!//use actual PCM data
36//!let input = DualPcm {
37//!    left: &[0u16, 0],
38//!    right: &[0u16, 0],
39//!};
40//!
41//!let mut mp3_out_buffer = Vec::new();
42//!mp3_out_buffer.reserve(mp3lame_encoder::max_required_buffer_size(input.left.len()));
43//!let encoded_size = mp3_encoder.encode(input, mp3_out_buffer.spare_capacity_mut()).expect("To encode");
44//!unsafe {
45//!    mp3_out_buffer.set_len(mp3_out_buffer.len().wrapping_add(encoded_size));
46//!}
47//!
48//!let encoded_size = mp3_encoder.flush::<FlushNoGap>(mp3_out_buffer.spare_capacity_mut()).expect("to flush");
49//!unsafe {
50//!    mp3_out_buffer.set_len(mp3_out_buffer.len().wrapping_add(encoded_size));
51//!}
52//!//At this point your mp3_out_buffer should have full MP3 data, ready to be written on file system or whatever
53//!
54//!```
55
56#![no_std]
57#![warn(missing_docs)]
58#![allow(clippy::style)]
59#![allow(clippy::missing_safety_doc)]
60#![cfg_attr(rustfmt, rustfmt_skip)]
61
62#[cfg(feature = "std")]
63extern crate std;
64
65extern crate alloc;
66
67pub use mp3lame_sys as ffi;
68
69use alloc::vec::Vec;
70use core::mem::{self, MaybeUninit};
71use core::ptr::{self, NonNull};
72use core::{cmp, fmt};
73
74mod input;
75pub use input::*;
76
77///Maximum size of album art
78pub const MAX_ALBUM_ART_SIZE: usize = 128 * 1024;
79
80///Calculates maximum required size for specified number of samples.
81///
82///Note that actual requirement may vary depending on encoder parameters,
83///but this size should be generally enough for encoding given number of samples
84pub const fn max_required_buffer_size(sample_number: usize) -> usize {
85    //add 25% sample number + mp3 frame size 7200
86    let mut sample_extra_size = sample_number / 4;
87    if (sample_number % 4) > 0 {
88        sample_extra_size = sample_extra_size.wrapping_add(1);
89    }
90    sample_number.wrapping_add(sample_extra_size).wrapping_add(7200)
91}
92
93#[derive(Debug, Copy, Clone, Eq, PartialEq)]
94///ID3 setter errors
95pub enum Id3TagError {
96    ///Specified buffer exceed limit of 128kb
97    AlbumArtOverflow,
98}
99
100#[derive(Debug, Copy, Clone, Eq, PartialEq)]
101///Encoder builder errors
102pub enum BuildError {
103    ///Generic error, indicates invalid input or state
104    Generic,
105    ///Failed to allocate memory
106    NoMem,
107    ///Invalid brate
108    BadBRate,
109    ///Invalid sample frequency
110    BadSampleFreq,
111    ///Internal error
112    InternalError,
113    ///Other errors, most likely unexpected.
114    Other(libc::c_int),
115}
116
117impl BuildError {
118    #[inline(always)]
119    fn from_c_int(code: libc::c_int) -> Result<(), Self> {
120        if code >= 0 {
121            return Ok(())
122        }
123
124        match code {
125            -1 => Err(Self::Generic),
126            -10 => Err(Self::NoMem),
127            -11 => Err(Self::BadBRate),
128            -12 => Err(Self::BadSampleFreq),
129            -13 => Err(Self::InternalError),
130            _ => Err(Self::Other(code)),
131        }
132    }
133}
134
135#[cfg(feature = "std")]
136impl std::error::Error for BuildError {
137}
138
139impl fmt::Display for BuildError {
140    #[inline]
141    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
142        match self {
143            Self::Generic => fmt.write_str("error"),
144            Self::NoMem => fmt.write_str("alloc failure"),
145            Self::BadBRate => fmt.write_str("bad bitrate"),
146            Self::BadSampleFreq => fmt.write_str("bad sample frequency"),
147            Self::InternalError => fmt.write_str("internal error"),
148            Self::Other(code) => fmt.write_fmt(format_args!("error code={code}")),
149        }
150    }
151}
152
153#[derive(Debug, Copy, Clone, Eq, PartialEq)]
154///Encoder errors
155pub enum EncodeError {
156    ///Indicates output buffer is insufficient.
157    ///
158    ///Consider using [max_required_buffer_size](max_required_buffer_size) to determine required
159    ///space to alloc.
160    BufferTooSmall,
161    ///Failed to allocate memory
162    NoMem,
163    ///Invalid encoder state
164    ///
165    ///Should not happen if encoder created through builder
166    InvalidState,
167    ///Psycho acoustic problems, whatever it means.
168    PsychoAcoustic,
169    ///Other errors, most likely unexpected.
170    Other(libc::c_int),
171}
172
173impl EncodeError {
174    #[inline(always)]
175    fn from_c_int(code: libc::c_int) -> Result<usize, Self> {
176        if code >= 0 {
177            return Ok(code as usize)
178        }
179
180        match code {
181            -1 => Err(Self::BufferTooSmall),
182            -2 => Err(Self::NoMem),
183            -3 => Err(Self::InvalidState),
184            -4 => Err(Self::PsychoAcoustic),
185            _ => Err(Self::Other(code)),
186        }
187    }
188}
189
190#[cfg(feature = "std")]
191impl std::error::Error for EncodeError {
192}
193
194impl fmt::Display for EncodeError {
195    #[inline]
196    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
197        match self {
198            Self::BufferTooSmall => fmt.write_str("output buffer is insufficient for encoder output"),
199            Self::NoMem => fmt.write_str("alloc failure"),
200            Self::InvalidState => fmt.write_str("attempt to use uninitialized encoder"),
201            Self::PsychoAcoustic => fmt.write_str("psycho acoustic problems"),
202            Self::Other(code) => fmt.write_fmt(format_args!("error code={code}")),
203        }
204    }
205}
206
207
208///Enumeration of valid values for `set_brate`
209#[derive(Copy, Clone)]
210#[repr(u16)]
211pub enum Bitrate {
212    ///8_000
213    Kbps8 = 8,
214    ///16_000
215    Kbps16 = 16,
216    ///24_000
217    Kbps24 = 24,
218    ///32_000
219    Kbps32 = 32,
220    ///40_000
221    Kbps40 = 40,
222    ///48_000
223    Kbps48 = 48,
224    ///64_000
225    Kbps64 = 64,
226    ///80_000
227    Kbps80 = 80,
228    ///96_000
229    Kbps96 = 96,
230    ///112_000
231    Kbps112 = 112,
232    ///128_000
233    Kbps128 = 128,
234    ///160_000
235    Kbps160 = 160,
236    ///192_000
237    Kbps192 = 192,
238    ///224_000
239    Kbps224 = 224,
240    ///256_000
241    Kbps256 = 256,
242    ///320_000
243    Kbps320 = 320,
244}
245
246///Alias to `Bitrate` with incorrect spelling
247pub use Bitrate as Birtate;
248
249#[derive(Copy, Clone)]
250#[repr(u8)]
251///Possible VBR types
252pub enum VbrMode {
253    ///Off.
254    Off = ffi::vbr_mode::vbr_off as u8,
255    ///MT.
256    Mt = ffi::vbr_mode::vbr_mt as u8,
257    ///RH.
258    Rh = ffi::vbr_mode::vbr_rh as u8,
259    ///ABR.
260    Abr = ffi::vbr_mode::vbr_abr as u8,
261    ///MTRH.
262    Mtrh = ffi::vbr_mode::vbr_mtrh as u8,
263}
264
265impl Default for VbrMode {
266    #[inline(always)]
267    fn default() -> Self {
268        Self::Mtrh
269    }
270}
271
272#[derive(Copy, Clone)]
273#[repr(u8)]
274///Possible modes for encoder
275pub enum Mode {
276    ///Mono.
277    Mono = ffi::MPEG_mode::MONO as u8,
278    ///Stereo.
279    Stereo = ffi::MPEG_mode::STEREO as u8,
280    ///Joint stereo.
281    JointStereo = ffi::MPEG_mode::JOINT_STEREO as u8,
282    ///Dual channel
283    ///
284    ///Unsupported so far.
285    DaulChannel = ffi::MPEG_mode::DUAL_CHANNEL as u8,
286    ///Not set.
287    NotSet = ffi::MPEG_mode::NOT_SET as u8,
288}
289
290///Possible quality parameter.
291///From best(0) to worst(9)
292#[derive(Copy, Clone)]
293#[repr(u8)]
294pub enum Quality {
295    ///Best possible quality
296    Best = 0,
297    ///Second best
298    SecondBest = 1,
299    ///Close to best
300    NearBest = 2,
301    ///Very nice
302    VeryNice = 3,
303    ///Nice
304    Nice = 4,
305    ///Good
306    Good = 5,
307    ///Decent
308    Decent = 6,
309    ///Okayish
310    Ok = 7,
311    ///Almost worst
312    SecondWorst = 8,
313    ///Worst
314    Worst = 9,
315}
316
317#[derive(Copy, Clone)]
318///ID3 tag as raw bytes.
319///
320///Use empty slice for `None`
321///
322///At the current moment, only up to 250 characters will be copied.
323pub struct Id3Tag<'a> {
324    ///Track's Title
325    pub title: &'a [u8],
326    ///Artist name
327    pub artist: &'a [u8],
328    ///Album name
329    pub album: &'a [u8],
330    ///Album art
331    ///
332    ///Must be image data.
333    ///
334    ///Allowed formats: PNG, JPG, GIF
335    ///
336    ///Maximum size is defined by constant MAX_ALBUM_ART_SIZE
337    ///When setting this metadata, make sure allocate at least MAX_ALBUM_ART_SIZE
338    pub album_art: &'a [u8],
339    ///Year
340    pub year: &'a [u8],
341    ///Comment
342    pub comment: &'a [u8],
343}
344
345impl Id3Tag<'_> {
346    #[inline(always)]
347    ///Returns true if any is set
348    pub const fn is_any_set(&self) -> bool {
349        !self.title.is_empty() || !self.artist.is_empty() || !self.album.is_empty() || !self.album_art.is_empty() || !self.year.is_empty() || !self.comment.is_empty()
350    }
351}
352
353///Builder of C LAME encoder.
354pub struct Builder {
355    inner: NonNull<ffi::lame_global_flags>,
356}
357
358impl Builder {
359    #[inline]
360    ///Creates new encoder with default parameters: J-Stereo, 44.1khz 128kbps CBR mp3 file at quality 5
361    ///
362    ///Returns `None` if unable to allocate struct.
363    pub fn new() -> Option<Self> {
364        let ptr = unsafe {
365            ffi::lame_init()
366        };
367
368        NonNull::new(ptr).map(|inner| Self {
369            inner
370        })
371    }
372
373    #[inline(always)]
374    ///Get access to underlying LAME structure, without dropping ownership.
375    ///
376    ///User must guarantee not to close or dealloc this pointer
377    pub unsafe fn as_ptr(&mut self) -> *mut ffi::lame_global_flags {
378        self.ptr()
379    }
380
381    #[inline(always)]
382    fn ptr(&mut self) -> *mut ffi::lame_global_flags {
383        self.inner.as_ptr()
384    }
385
386    #[inline]
387    ///Sets sample rate.
388    ///
389    ///Defaults to 44_100.
390    ///
391    ///Returns whether it is supported or not.
392    pub fn set_sample_rate(&mut self, rate: u32) -> Result<(), BuildError> {
393        let res = unsafe {
394            ffi::lame_set_in_samplerate(self.ptr(), rate.try_into().unwrap_or(libc::c_int::MAX))
395        };
396
397        BuildError::from_c_int(res)
398    }
399
400    #[inline]
401    ///Sets sample rate using the builder pattern.
402    /// 
403    ///Defaults to 44_100.
404    /// 
405    ///Returns an error if it is not supported.
406    pub fn with_sample_rate(mut self, rate: u32) -> Result<Self, BuildError> {
407        self.set_sample_rate(rate)?;
408        Ok(self)
409    }
410
411    #[inline]
412    ///Sets number of channels.
413    ///
414    ///Defaults to 2.
415    ///
416    ///Returns whether it is supported or not.
417    pub fn set_num_channels(&mut self, num: u8) -> Result<(), BuildError> {
418        let res = unsafe {
419            ffi::lame_set_num_channels(self.ptr(), num as _)
420        };
421
422        BuildError::from_c_int(res)
423    }
424
425    #[inline]
426    ///Sets sample rate using the builder pattern.
427    ///
428    ///Defaults to 2.
429    ///
430    ///Returns an error if it is not supported.
431    pub fn with_num_channels(mut self, num: u8) -> Result<Self, BuildError> {
432        self.set_num_channels(num)?;
433        Ok(self)
434    }
435
436    #[inline]
437    ///Sets bitrate (as kbps).
438    ///
439    ///Defaults to compression ratio of 11.
440    ///
441    ///Returns whether it is supported or not.
442    pub fn set_brate(&mut self, brate: Bitrate) -> Result<(), BuildError> {
443        let res = unsafe {
444            ffi::lame_set_brate(self.ptr(), brate as _)
445        };
446
447        BuildError::from_c_int(res)
448    }
449
450    #[inline]
451    ///Sets bitrate (as kbps) using the builder pattern.
452    ///
453    ///Defaults to compression ratio of 11.
454    ///
455    ///Returns an error if it is not supported.
456    pub fn with_brate(mut self, brate: Bitrate) -> Result<Self, BuildError> {
457        self.set_brate(brate)?;
458        Ok(self)
459    }
460
461    #[inline]
462    ///Sets MPEG mode.
463    ///
464    ///Default is picked by LAME depending on compression ration and input channels.
465    ///
466    ///Returns whether it is supported or not.
467    pub fn set_mode(&mut self, mode: Mode) -> Result<(), BuildError> {
468        let res = unsafe {
469            ffi::lame_set_mode(self.ptr(), mode as _)
470        };
471
472        BuildError::from_c_int(res)
473    }
474
475    #[inline]
476    ///Sets MPEG mode using the builder pattern.
477    ///
478    ///Default is picked by LAME depending on compression ration and input channels.
479    ///
480    ///Returns an error if it is not supported.
481    pub fn with_mode(mut self, mode: Mode) -> Result<Self, BuildError> {
482        self.set_mode(mode)?;
483        Ok(self)
484    }
485
486    #[inline]
487    ///Sets quality.
488    ///
489    ///Default is good one(5)
490    ///
491    ///Returns whether it is supported or not.
492    pub fn set_quality(&mut self, quality: Quality) -> Result<(), BuildError> {
493        let res = unsafe {
494            ffi::lame_set_quality(self.ptr(), quality as _)
495        };
496
497        BuildError::from_c_int(res)
498    }
499
500    #[inline]
501    ///Sets quality using the builder pattern.
502    ///
503    ///Default is good one(5)
504    ///
505    ///Returns an error if it is not supported.
506    pub fn with_quality(mut self, quality: Quality) -> Result<Self, BuildError> {
507        self.set_quality(quality)?;
508        Ok(self)
509    }
510
511    #[inline]
512    ///Sets VBR quality.
513    ///
514    ///Returns whether it is supported or not.
515    pub fn set_vbr_quality(&mut self, quality: Quality) -> Result<(), BuildError> {
516        let res = unsafe {
517            ffi::lame_set_VBR_q(self.ptr(), quality as _)
518        };
519
520        BuildError::from_c_int(res)
521    }
522
523    #[inline]
524    ///Sets VBR quality using the builder pattern.
525    /// 
526    ///Returns an error if it is not supported.
527    pub fn with_vbr_quality(mut self, quality: Quality) -> Result<Self, BuildError> {
528        self.set_vbr_quality(quality)?;
529        Ok(self)
530    }
531
532    #[inline]
533    ///Sets whether to write VBR tag.
534    ///
535    ///Default is true.
536    ///
537    ///Returns whether it is supported or not.
538    pub fn set_to_write_vbr_tag(&mut self, value: bool) -> Result<(), BuildError> {
539        let res = unsafe {
540            ffi::lame_set_bWriteVbrTag(self.ptr(), value as _)
541        };
542
543        BuildError::from_c_int(res)
544    }
545
546    #[inline]
547    ///Sets whether to write VBR tag using the builder pattern.
548    ///
549    ///Default is true.
550    ///
551    ///Returns an error if it is not supported.
552    pub fn with_to_write_vbr_tag(mut self, value: bool) -> Result<Self, BuildError> {
553        self.set_to_write_vbr_tag(value)?;
554        Ok(self)
555    }
556
557    #[inline]
558    ///Sets VBR mode.
559    ///
560    ///Default is off (i.e. CBR)
561    ///
562    ///Returns whether it is supported or not.
563    pub fn set_vbr_mode(&mut self, value: VbrMode) -> Result<(), BuildError> {
564        let res = unsafe {
565            ffi::lame_set_VBR(self.ptr(), value as _)
566        };
567
568        BuildError::from_c_int(res)
569    }
570
571    #[inline]
572    ///Sets VBR mode using the bulder pattern.
573    /// 
574    ///Default is off (i.e. CBR)
575    /// 
576    ///Returns an error if it is not supported.
577    pub fn with_vbr_mode(mut self, value: VbrMode) -> Result<Self, BuildError> {
578        self.set_vbr_mode(value)?;
579        Ok(self)
580    }
581
582    #[inline]
583    ///Sets id3tag tag.
584    ///
585    ///If [FlushGap](FlushGap) is used, then `v1` will not be added.
586    ///But `v2` is always added at the beginning.
587    ///
588    ///Returns whether it is supported or not.
589    pub fn set_id3_tag(&mut self, value: Id3Tag<'_>) -> Result<(), Id3TagError> {
590        if !value.is_any_set() {
591            return Ok(());
592        }
593
594        const MAX_BUFFER: usize = 250;
595        let mut buffer = [0u8; MAX_BUFFER + 1];
596
597        unsafe {
598            ffi::id3tag_init(self.ptr());
599            ffi::id3tag_add_v2(self.ptr());
600
601            if !value.album_art.is_empty() {
602                let size = value.album_art.len();
603                if size > MAX_ALBUM_ART_SIZE {
604                    return Err(Id3TagError::AlbumArtOverflow);
605                }
606                let ptr = value.album_art.as_ptr();
607                ffi::id3tag_set_albumart(self.ptr(), ptr as _, size);
608            }
609
610            if !value.title.is_empty() {
611                let size = cmp::min(MAX_BUFFER, value.title.len());
612                ptr::copy_nonoverlapping(value.title.as_ptr(), buffer.as_mut_ptr(), size);
613                buffer[size] = 0;
614                ffi::id3tag_set_title(self.ptr(), buffer.as_ptr() as _);
615            }
616
617            if !value.album.is_empty() {
618                let size = cmp::min(MAX_BUFFER, value.album.len());
619                ptr::copy_nonoverlapping(value.album.as_ptr(), buffer.as_mut_ptr(), size);
620                buffer[size] = 0;
621                ffi::id3tag_set_album(self.ptr(), buffer.as_ptr() as _);
622            }
623
624            if !value.artist.is_empty() {
625                let size = cmp::min(MAX_BUFFER, value.artist.len());
626                ptr::copy_nonoverlapping(value.artist.as_ptr(), buffer.as_mut_ptr(), size);
627                buffer[size] = 0;
628                ffi::id3tag_set_artist(self.ptr(), buffer.as_ptr() as _);
629            }
630
631            if !value.year.is_empty() {
632                let size = cmp::min(MAX_BUFFER, value.year.len());
633                ptr::copy_nonoverlapping(value.year.as_ptr(), buffer.as_mut_ptr(), size);
634                buffer[size] = 0;
635                ffi::id3tag_set_year(self.ptr(), buffer.as_ptr() as _);
636            }
637
638            if !value.comment.is_empty() {
639                let size = cmp::min(MAX_BUFFER, value.comment.len());
640                ptr::copy_nonoverlapping(value.comment.as_ptr(), buffer.as_mut_ptr(), size);
641                buffer[size] = 0;
642                ffi::id3tag_set_comment(self.ptr(), buffer.as_ptr() as _);
643            }
644        }
645
646        Ok(())
647    }
648
649    #[inline]
650    ///Sets id3tag tag using the builder pattern.
651    ///
652    ///If [FlushGap](FlushGap) is used, then `v1` will not be added.
653    /// 
654    ///Returns an error if it is not supported.
655    pub fn with_id3_tag(mut self, value: Id3Tag<'_>) -> Result<Self, Id3TagError> {
656        self.set_id3_tag(value)?;
657        Ok(self)
658    }
659
660    #[inline]
661    ///Attempts to initialize encoder with specified parameters.
662    ///
663    ///Returns `None` if parameters are invalid or incompatible.
664    pub fn build(mut self) -> Result<Encoder, BuildError> {
665        let res = unsafe {
666            ffi::lame_init_params(self.ptr())
667        };
668
669        match BuildError::from_c_int(res) {
670            Ok(()) => {
671                let inner = self.inner;
672                mem::forget(self);
673                Ok(Encoder { inner })
674            },
675            Err(error) => Err(error),
676        }
677    }
678}
679
680impl Drop for Builder {
681    #[inline]
682    fn drop(&mut self) {
683        unsafe {
684            ffi::lame_close(self.ptr())
685        };
686    }
687}
688
689///LAME Encoder.
690pub struct Encoder {
691    inner: NonNull<ffi::lame_global_flags>,
692}
693
694impl Encoder {
695    #[inline(always)]
696    fn ptr(&self) -> *mut ffi::lame_global_flags {
697        self.inner.as_ptr()
698    }
699
700    #[inline]
701    ///Returns sample rate.
702    pub fn sample_rate(&self) -> u32 {
703        unsafe {
704            ffi::lame_get_in_samplerate(self.ptr()) as u32
705        }
706    }
707
708    #[inline]
709    ///Returns number of channels.
710    pub fn num_channels(&self) -> u8 {
711        unsafe {
712            ffi::lame_get_num_channels(self.ptr()) as u8
713        }
714    }
715
716    #[inline]
717    ///Attempts to encode PCM data, writing whatever available onto `output` buffer
718    ///
719    ///### Arguments:
720    ///
721    /// - `input` - Data input. Can be [MonoPcm](MonoPcm), [DualPcm](DualPcm) or [InterleavedPcm](InterleavedPcm)
722    /// - `output` - Output buffer to write into.
723    ///
724    ///### Result:
725    ///On success, returns number of bytes written (can be 0).
726    ///Otherwise returns error indicating potential issue.
727    pub fn encode(&mut self, input: impl EncoderInput, output: &mut [MaybeUninit<u8>]) -> Result<usize, EncodeError> {
728        let output_len = output.len();
729        let output_buf = output.as_mut_ptr();
730
731        let result = input.encode(self, output_buf as _, output_len);
732
733        EncodeError::from_c_int(result)
734    }
735
736    #[inline(always)]
737    ///Attempts to encode PCM data, writing whatever available onto `output` buffer
738    ///
739    ///`output` size is adjusted on success only
740    ///
741    ///Refer for details to `encode()`
742    pub fn encode_to_vec(&mut self, input: impl EncoderInput, output: &mut Vec<u8>) -> Result<usize, EncodeError> {
743        let original_len = output.len();
744        match self.encode(input, output.spare_capacity_mut()) {
745            Ok(written) => {
746                unsafe {
747                    output.set_len(original_len.saturating_add(written));
748                }
749                Ok(written)
750            },
751            Err(error) => Err(error),
752        }
753    }
754
755    #[inline]
756    ///Attempts flush all data, writing whatever available onto `output` buffer
757    ///Padding with 0 to complete MP3
758    ///
759    ///### Type:
760    ///
761    ///- [FlushNoGap](FlushNoGap) - performs flush, using ancillary data to fill gaps;
762    ///- [FlushGap](FlushGap) - performs flush, padding with 0;
763    ///
764    ///### Arguments:
765    ///
766    /// - `output` - Output buffer to write into. As it is final action, you need at least 7200 bytes to hold at MP3 data.
767    ///
768    ///### Result:
769    ///On success, returns number of bytes written (can be 0).
770    ///Otherwise returns error indicating potential issue.
771    pub fn flush<T: EncoderFlush>(&mut self, output: &mut [MaybeUninit<u8>]) -> Result<usize, EncodeError> {
772        let output_len = output.len();
773        let output_buf = output.as_mut_ptr();
774
775        let result = T::flush(self, output_buf as _, output_len);
776
777        EncodeError::from_c_int(result)
778    }
779
780    #[inline(always)]
781    ///Attempts flush all data, writing whatever available onto `output` buffer.
782    ///
783    ///`output` size is adjusted on success only
784    ///
785    ///Refer for details to `flush()`
786    pub fn flush_to_vec<T: EncoderFlush>(&mut self, output: &mut Vec<u8>) -> Result<usize, EncodeError> {
787        let original_len = output.len();
788        match self.flush::<T>(output.spare_capacity_mut()) {
789            Ok(written) => {
790                unsafe {
791                    output.set_len(original_len.saturating_add(written));
792                }
793                Ok(written)
794            },
795            Err(error) => Err(error),
796        }
797    }
798}
799
800impl Drop for Encoder {
801    #[inline]
802    fn drop(&mut self) {
803        unsafe {
804            ffi::lame_close(self.ptr())
805        };
806    }
807}
808
809/// According to LAME 3.99.5 HACKING, it is thread-safe.
810unsafe impl Send for Encoder {}
811/// According to LAME 3.99.5 HACKING, it is thread-safe.
812unsafe impl Sync for Encoder {}
813
814///Creates default encoder with 192kbps bitrate and best possible quality.
815pub fn encoder() -> Result<Encoder, BuildError> {
816    match Builder::new() {
817        Some(mut builder) => {
818            builder.set_brate(Bitrate::Kbps192)?;
819            builder.set_quality(Quality::Best)?;
820            builder.build()
821        },
822        None => Err(BuildError::NoMem)
823    }
824}