1use crate::encoder::{
7 shine_encode_buffer_interleaved, shine_flush, shine_initialise, shine_set_config_mpeg_defaults,
8 ShineConfig, ShineMpeg, ShineWave, NONE,
9};
10use crate::error::{ConfigError, EncoderError, InputDataError};
11use crate::types::ShineGlobalConfig;
12use std::collections::VecDeque;
13
14pub const SUPPORTED_SAMPLE_RATES: &[u32] = &[
16 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, ];
20
21pub const SUPPORTED_BITRATES: &[u32] = &[
23 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 192, 224, 256, 320,
24];
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum StereoMode {
29 Stereo = 0,
31 JointStereo = 1,
33 DualChannel = 2,
35 Mono = 3,
37}
38
39#[derive(Debug, Clone)]
41pub struct Mp3EncoderConfig {
42 pub sample_rate: u32,
44 pub bitrate: u32,
46 pub channels: u8,
48 pub stereo_mode: StereoMode,
50 pub copyright: bool,
52 pub original: bool,
54}
55
56impl Default for Mp3EncoderConfig {
57 fn default() -> Self {
58 Self {
59 sample_rate: 44100,
60 bitrate: 128,
61 channels: 2,
62 stereo_mode: StereoMode::Stereo,
63 copyright: false,
64 original: true,
65 }
66 }
67}
68
69impl Mp3EncoderConfig {
70 pub fn new() -> Self {
72 Self::default()
73 }
74
75 pub fn sample_rate(mut self, sample_rate: u32) -> Self {
77 self.sample_rate = sample_rate;
78 self
79 }
80
81 pub fn bitrate(mut self, bitrate: u32) -> Self {
83 self.bitrate = bitrate;
84 self
85 }
86
87 pub fn channels(mut self, channels: u8) -> Self {
89 self.channels = channels;
90 self
91 }
92
93 pub fn stereo_mode(mut self, mode: StereoMode) -> Self {
95 self.stereo_mode = mode;
96 self
97 }
98
99 pub fn copyright(mut self, copyright: bool) -> Self {
101 self.copyright = copyright;
102 self
103 }
104
105 pub fn original(mut self, original: bool) -> Self {
107 self.original = original;
108 self
109 }
110
111 pub fn validate(&self) -> Result<(), ConfigError> {
113 if !SUPPORTED_SAMPLE_RATES.contains(&self.sample_rate) {
115 return Err(ConfigError::UnsupportedSampleRate(self.sample_rate));
116 }
117
118 if !SUPPORTED_BITRATES.contains(&self.bitrate) {
120 return Err(ConfigError::UnsupportedBitrate(self.bitrate));
121 }
122
123 if self.channels == 0 || self.channels > 2 {
125 return Err(ConfigError::InvalidChannels);
126 }
127
128 match (self.channels, self.stereo_mode) {
130 (1, StereoMode::Mono) => {}
131 (2, StereoMode::Stereo | StereoMode::JointStereo | StereoMode::DualChannel) => {}
132 (channels, mode) => {
133 return Err(ConfigError::InvalidStereoMode {
134 mode: format!("{:?}", mode),
135 channels,
136 });
137 }
138 }
139
140 let shine_result =
142 crate::encoder::shine_check_config(self.sample_rate as i32, self.bitrate as i32);
143
144 if shine_result < 0 {
145 let mpeg_version = if self.sample_rate <= 12000 {
147 "MPEG-2.5"
148 } else if self.sample_rate <= 24000 {
149 "MPEG-2"
150 } else {
151 "MPEG-1"
152 };
153
154 let reason = match mpeg_version {
155 "MPEG-2.5" => format!(
156 "MPEG-2.5 ({}Hz) only supports bitrates up to 64 kbps",
157 self.sample_rate
158 ),
159 "MPEG-2" => format!(
160 "MPEG-2 ({}Hz) only supports bitrates up to 160 kbps",
161 self.sample_rate
162 ),
163 "MPEG-1" => format!(
164 "MPEG-1 ({}Hz) only supports bitrates from 32 to 320 kbps",
165 self.sample_rate
166 ),
167 _ => "Invalid combination".to_string(),
168 };
169
170 return Err(ConfigError::IncompatibleRateCombination {
171 sample_rate: self.sample_rate,
172 bitrate: self.bitrate,
173 reason,
174 });
175 }
176
177 Ok(())
178 }
179}
180
181#[derive(Debug)]
183pub struct Mp3Encoder {
184 config: Box<ShineGlobalConfig>,
186 encoder_config: Mp3EncoderConfig,
188 samples_per_frame: usize,
190 input_buffer: VecDeque<i16>,
192 finished: bool,
194}
195
196impl Mp3Encoder {
197 pub fn new(config: Mp3EncoderConfig) -> Result<Self, EncoderError> {
199 config.validate()?;
201
202 let shine_config = Self::create_shine_config(&config)?;
204
205 let global_config = shine_initialise(&shine_config).map_err(EncoderError::Encoding)?;
207
208 let samples_per_channel = crate::encoder::shine_samples_per_pass(&global_config) as usize;
210 let samples_per_frame = samples_per_channel * config.channels as usize;
211
212 Ok(Self {
213 config: global_config,
214 encoder_config: config,
215 samples_per_frame,
216 input_buffer: VecDeque::new(),
217 finished: false,
218 })
219 }
220
221 pub fn config(&self) -> &Mp3EncoderConfig {
223 &self.encoder_config
224 }
225
226 pub fn samples_per_frame(&self) -> usize {
228 self.samples_per_frame
229 }
230
231 pub fn shine_config(&mut self) -> &mut ShineGlobalConfig {
233 &mut self.config
234 }
235
236 pub fn encode_interleaved(&mut self, pcm_data: &[i16]) -> Result<Vec<Vec<u8>>, EncoderError> {
244 if self.finished {
245 return Err(EncoderError::InternalState(
246 "Encoder has been finished".to_string(),
247 ));
248 }
249
250 if pcm_data.is_empty() {
252 return Err(EncoderError::InputData(InputDataError::EmptyInput));
253 }
254
255 self.input_buffer.extend(pcm_data);
257
258 let mut output_frames = Vec::new();
259
260 while self.input_buffer.len() >= self.samples_per_frame {
262 let frame_data: Vec<i16> = self.input_buffer.drain(..self.samples_per_frame).collect();
263
264 let (mp3_data, written) =
266 unsafe { shine_encode_buffer_interleaved(&mut self.config, frame_data.as_ptr()) }
267 .map_err(EncoderError::Encoding)?;
268
269 if written > 0 {
270 output_frames.push(mp3_data[..written].to_vec());
271 }
272 }
273
274 Ok(output_frames)
275 }
276
277 pub fn encode_separate_channels(
286 &mut self,
287 left_channel: &[i16],
288 right_channel: Option<&[i16]>,
289 ) -> Result<Vec<Vec<u8>>, EncoderError> {
290 if self.finished {
291 return Err(EncoderError::InternalState(
292 "Encoder has been finished".to_string(),
293 ));
294 }
295
296 if left_channel.is_empty() {
298 return Err(EncoderError::InputData(InputDataError::EmptyInput));
299 }
300
301 match (self.encoder_config.channels, right_channel) {
303 (1, None) => {
304 self.encode_interleaved(left_channel)
306 }
307 (2, Some(right)) => {
308 if left_channel.len() != right.len() {
309 return Err(EncoderError::InputData(
310 InputDataError::InvalidChannelCount {
311 expected: left_channel.len(),
312 actual: right.len(),
313 },
314 ));
315 }
316
317 let mut interleaved = Vec::with_capacity(left_channel.len() * 2);
319 for (l, r) in left_channel.iter().zip(right.iter()) {
320 interleaved.push(*l);
321 interleaved.push(*r);
322 }
323
324 self.encode_interleaved(&interleaved)
325 }
326 (1, Some(_)) => Err(EncoderError::InputData(
327 InputDataError::InvalidChannelCount {
328 expected: 1,
329 actual: 2,
330 },
331 )),
332 (2, None) => Err(EncoderError::InputData(
333 InputDataError::InvalidChannelCount {
334 expected: 2,
335 actual: 1,
336 },
337 )),
338 _ => unreachable!(),
339 }
340 }
341
342 pub fn finish(&mut self) -> Result<Vec<u8>, EncoderError> {
347 if self.finished {
348 return Ok(Vec::new());
349 }
350
351 self.finished = true;
352
353 let mut final_output = Vec::new();
355
356 if !self.input_buffer.is_empty() {
357 while self.input_buffer.len() < self.samples_per_frame {
359 self.input_buffer.push_back(0);
360 }
361
362 let frame_data: Vec<i16> = self.input_buffer.drain(..).collect();
363
364 let (mp3_data, written) =
365 unsafe { shine_encode_buffer_interleaved(&mut self.config, frame_data.as_ptr()) }
366 .map_err(EncoderError::Encoding)?;
367
368 if written > 0 {
369 final_output.extend_from_slice(&mp3_data[..written]);
370 }
371 }
372
373 let (flush_data, flush_written) = shine_flush(&mut self.config);
375 if flush_written > 0 {
376 final_output.extend_from_slice(&flush_data[..flush_written]);
377 }
378
379 Ok(final_output)
380 }
381
382 pub fn buffered_samples(&self) -> usize {
384 self.input_buffer.len()
385 }
386
387 pub fn is_finished(&self) -> bool {
389 self.finished
390 }
391
392 fn create_shine_config(config: &Mp3EncoderConfig) -> Result<ShineConfig, ConfigError> {
394 let mut mpeg = ShineMpeg {
395 mode: config.stereo_mode as i32,
396 bitr: config.bitrate as i32,
397 emph: NONE,
398 copyright: if config.copyright { 1 } else { 0 },
399 original: if config.original { 1 } else { 0 },
400 };
401
402 shine_set_config_mpeg_defaults(&mut mpeg);
404
405 mpeg.mode = config.stereo_mode as i32;
407 mpeg.bitr = config.bitrate as i32;
408 mpeg.copyright = if config.copyright { 1 } else { 0 };
409 mpeg.original = if config.original { 1 } else { 0 };
410
411 let wave = ShineWave {
412 channels: config.channels as i32,
413 samplerate: config.sample_rate as i32,
414 };
415
416 Ok(ShineConfig { wave, mpeg })
417 }
418}
419
420impl Drop for Mp3Encoder {
421 fn drop(&mut self) {
422 }
426}
427
428pub fn encode_pcm_to_mp3(
437 config: Mp3EncoderConfig,
438 pcm_data: &[i16],
439) -> Result<Vec<u8>, EncoderError> {
440 let mut encoder = Mp3Encoder::new(config)?;
441
442 let mut mp3_data = Vec::new();
443
444 let frames = encoder.encode_interleaved(pcm_data)?;
446 for frame in frames {
447 mp3_data.extend(frame);
448 }
449
450 let final_data = encoder.finish()?;
452 mp3_data.extend(final_data);
453
454 Ok(mp3_data)
455}