1use super::pcm::*;
3use crate::ext::io::*;
4use crate::scripts::base::*;
5use crate::types::*;
6use anyhow::Result;
7use libflac_sys::*;
8use std::ffi::CStr;
9use std::io::{Read, Seek, Write};
10
11extern "C" fn write_callback(
12 _encoder: *const FLAC__StreamEncoder,
13 buffer: *const u8,
14 bytes: usize,
15 _samples: u32,
16 _current_frame: u32,
17 client_data: *mut std::ffi::c_void,
18) -> FLAC__StreamEncoderWriteStatus {
19 let writer = unsafe { &mut *(client_data as *mut &mut dyn WriteSeek) };
20 let slice = unsafe { std::slice::from_raw_parts(buffer, bytes) };
21 match writer.write_all(slice) {
22 Ok(_) => FLAC__STREAM_ENCODER_WRITE_STATUS_OK,
23 Err(_) => FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR,
24 }
25}
26
27extern "C" fn tell_callback(
28 _encoder: *const FLAC__StreamEncoder,
29 absolute_byte_offset: *mut u64,
30 client_data: *mut std::ffi::c_void,
31) -> FLAC__StreamEncoderTellStatus {
32 if absolute_byte_offset.is_null() {
33 return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR;
34 }
35 let writer = unsafe { &mut *(client_data as *mut &mut dyn WriteSeek) };
36 match writer.stream_position() {
37 Ok(pos) => {
38 unsafe {
39 *absolute_byte_offset = pos;
40 }
41 FLAC__STREAM_ENCODER_TELL_STATUS_OK
42 }
43 Err(_) => FLAC__STREAM_ENCODER_TELL_STATUS_ERROR,
44 }
45}
46
47extern "C" fn seek_callback(
48 _encoder: *const FLAC__StreamEncoder,
49 absolute_byte_offset: u64,
50 client_data: *mut std::ffi::c_void,
51) -> FLAC__StreamEncoderSeekStatus {
52 let writer = unsafe { &mut *(client_data as *mut &mut dyn WriteSeek) };
53 match writer.seek(std::io::SeekFrom::Start(absolute_byte_offset)) {
54 Ok(_) => FLAC__STREAM_ENCODER_SEEK_STATUS_OK,
55 Err(_) => FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR,
56 }
57}
58
59fn handle_init_error(status: u32) -> Result<()> {
60 if status == 0 {
61 return Ok(());
62 }
63 let index = status as usize;
64 let s = unsafe { CStr::from_ptr(FLAC__StreamEncoderInitStatusString[index]) };
65 Err(anyhow::anyhow!(
66 "FLAC encoder error: {}",
67 s.to_string_lossy()
68 ))
69}
70
71struct EncoderHandle {
72 encoder: *mut FLAC__StreamEncoder,
73}
74
75impl Drop for EncoderHandle {
76 fn drop(&mut self) {
77 unsafe {
78 FLAC__stream_encoder_delete(self.encoder);
79 }
80 }
81}
82
83pub fn write_flac<W: Write + Seek, R: Read>(
90 header: &PcmFormat,
91 mut reader: R,
92 mut writer: W,
93 config: &ExtraConfig,
94) -> Result<()> {
95 if header.bits_per_sample > 32 {
96 return Err(anyhow::anyhow!(
97 "FLAC supports up to 32 bits per sample, got {}",
98 header.bits_per_sample
99 ));
100 }
101 let encoder = unsafe { FLAC__stream_encoder_new() };
102 if encoder.is_null() {
103 return Err(anyhow::anyhow!("Failed to create FLAC encoder"));
104 }
105 let encoder = EncoderHandle { encoder };
106 unsafe {
107 FLAC__stream_encoder_set_channels(encoder.encoder, header.channels as u32);
108 FLAC__stream_encoder_set_compression_level(encoder.encoder, config.flac_compression_level);
109 FLAC__stream_encoder_set_bits_per_sample(encoder.encoder, header.bits_per_sample as u32);
110 FLAC__stream_encoder_set_sample_rate(encoder.encoder, header.sample_rate);
111 FLAC__stream_encoder_set_verify(encoder.encoder, 1);
112 }
113 let mut raw_writer: &mut dyn WriteSeek = &mut writer;
114 let raw_writer = &mut raw_writer as *mut _;
115 handle_init_error(unsafe {
116 FLAC__stream_encoder_init_stream(
117 encoder.encoder,
118 Some(write_callback),
119 Some(seek_callback),
120 Some(tell_callback),
121 None,
122 raw_writer as *mut std::ffi::c_void,
123 )
124 })?;
125 let mut buf = Vec::<i32>::with_capacity(1024 * header.channels as usize);
126 buf.resize(buf.capacity(), 0);
127 let mut read_buf = Vec::<u8>::with_capacity(
128 (header.bits_per_sample / 8) as usize * 1024 * header.channels as usize,
129 );
130 read_buf.resize(read_buf.capacity(), 0);
131 loop {
132 let readed = reader.read(&mut read_buf)?;
133 if readed == 0 {
134 break;
135 }
136 let mut r = MemReaderRef::new(&read_buf[..readed]);
137 let samples =
138 readed as usize / (header.bits_per_sample as usize / 8) / header.channels as usize;
139 let mut i = 0;
140 for _ in 0..samples {
141 for _ in 0..header.channels {
142 let sample = match header.bits_per_sample {
143 8 => r.read_i8()? as i32,
144 16 => r.read_i16()? as i32,
145 24 => {
146 let b1 = r.read_u8()? as i32;
147 let b2 = r.read_u8()? as i32;
148 let b3 = r.read_u8()? as i32;
149 let mut val = (b3 << 16) | (b2 << 8) | b1;
150 if val & 0x800000 != 0 {
152 val |= !0xffffff;
153 }
154 val
155 }
156 32 => r.read_i32()?,
157 _ => {
158 return Err(anyhow::anyhow!(
159 "Unsupported bits per sample: {}",
160 header.bits_per_sample
161 ));
162 }
163 };
164 buf[i] = sample;
165 i += 1;
166 }
167 }
168 if samples == 0 {
169 break;
170 }
171 if unsafe {
172 FLAC__stream_encoder_process_interleaved(encoder.encoder, buf.as_ptr(), samples as u32)
173 } == 0
174 {
175 let state = unsafe { FLAC__stream_encoder_get_state(encoder.encoder) };
176 let s = unsafe { CStr::from_ptr(FLAC__StreamEncoderStateString[state as usize]) };
177 return Err(anyhow::anyhow!(
178 "FLAC encoding error: {}",
179 s.to_string_lossy()
180 ));
181 }
182 }
183 if unsafe { FLAC__stream_encoder_finish(encoder.encoder) } == 0 {
184 let state = unsafe { FLAC__stream_encoder_get_state(encoder.encoder) };
185 let s = unsafe { CStr::from_ptr(FLAC__StreamEncoderStateString[state as usize]) };
186 return Err(anyhow::anyhow!(
187 "FLAC encoding error: {}",
188 s.to_string_lossy()
189 ));
190 }
191 Ok(())
192}