diff --git a/flacenc-bin/src/main.rs b/flacenc-bin/src/main.rs index aa5469c..633492e 100644 --- a/flacenc-bin/src/main.rs +++ b/flacenc-bin/src/main.rs @@ -140,12 +140,8 @@ fn run_encoder( encoder_config: &config::Encoder, source: source::PreloadedSignal, ) -> Result { - if encoder_config.block_sizes.len() == 1 { - let block_size = encoder_config.block_sizes[0]; - coding::encode_with_fixed_block_size(encoder_config, source, block_size) - } else { - coding::encode_with_multiple_block_sizes(encoder_config, source) - } + let block_size = encoder_config.block_sizes[0]; + coding::encode_with_fixed_block_size(encoder_config, source, block_size) } fn main_body(args: Args) -> Result<(), i32> { diff --git a/report/bsbs.config.toml b/report/bsbs.config.toml deleted file mode 100644 index 9c5dc85..0000000 --- a/report/bsbs.config.toml +++ /dev/null @@ -1,4 +0,0 @@ -# Block-size beam-search searches the sequence of block sizes with using a -# beam-search algorithm. - -block_sizes = [4096, 8192] diff --git a/src/coding.rs b/src/coding.rs index d0d7f0f..355e159 100644 --- a/src/coding.rs +++ b/src/coding.rs @@ -15,10 +15,6 @@ //! Controller connecting coding algorithms. use std::cell::RefCell; -#[cfg(feature = "experimental")] -use std::collections::BTreeSet; -#[cfg(feature = "experimental")] -use std::sync::Arc; #[cfg(feature = "par")] use rayon::iter::IntoParallelIterator; @@ -37,15 +33,12 @@ use super::component::StreamInfo; use super::component::SubFrame; use super::component::Verbatim; use super::config; -#[cfg(feature = "experimental")] -use super::constant::BSBS_DEFAULT_BEAM_WIDTH_MULTIPLIER; use super::constant::MAX_LPC_ORDER; use super::error::SourceError; use super::lpc; use super::rice; use super::source::Context; use super::source::FrameBuf; -use super::source::Seekable; use super::source::Source; #[cfg(feature = "fakesimd")] @@ -544,217 +537,6 @@ pub fn encode_with_fixed_block_size( Ok(stream) } -/// A hypothesis for block-size beam search. -#[cfg(feature = "experimental")] -struct Hyp { - frame: Frame, - offset: usize, - block_size: usize, - samples: usize, - bits: usize, - back_pointer: Option>, - is_last: bool, - context: Context, -} - -#[cfg(feature = "experimental")] -impl Hyp { - /// Creates a new beam-search node connecting to the given `back_pointer`. - /// - /// # Error - /// - /// Returns `SourceError` when it failed to read from `src`. - pub fn new( - src: &mut T, - block_size: usize, - config: &config::Encoder, - stream_info: &StreamInfo, - back_pointer: Option>, - ) -> Result, SourceError> { - // OPTIMIZE ME: Heap allocation done for each hyp. - let mut framebuf = FrameBuf::with_size(stream_info.channels(), block_size); - let offset = back_pointer.as_ref().map_or(0, |h| h.next_offset()); - let mut ctx = back_pointer.as_ref().map_or_else( - || Context::new(stream_info.bits_per_sample(), stream_info.channels()), - |hyp| hyp.context.clone(), - ); - src.read_samples_from(offset, &mut framebuf, &mut ctx)?; - let frame_samples = std::cmp::min(src.len() - offset, block_size); - let frame = encode_frame(config, &framebuf, offset, stream_info); - let bits = frame.count_bits(); - let prev_samples = back_pointer.as_ref().map_or(0, |h| h.samples); - let prev_bits = back_pointer.as_ref().map_or(0, |h| h.bits); - Ok(Arc::new(Self { - frame, - offset, - block_size, - samples: prev_samples + frame_samples, - bits: prev_bits + bits, - back_pointer, - is_last: frame_samples != block_size, - context: ctx, - })) - } - - pub const fn next_offset(&self) -> usize { - self.offset + self.block_size - } - - pub fn bits_per_sample(&self) -> f64 { - self.bits as f64 / self.samples as f64 - } -} - -#[cfg(feature = "experimental")] -struct BeamSearch<'a, T: Seekable> { - config: &'a config::Encoder, - stream_info: &'a StreamInfo, - src: &'a mut T, - beam_width: usize, - best_hyp: Option>, - current_hyps: Vec>, - next_hyps: Vec>, - prune_markers: BTreeSet, -} - -#[cfg(feature = "experimental")] -impl<'a, T: Seekable> BeamSearch<'a, T> { - pub fn new( - config: &'a config::Encoder, - stream_info: &'a StreamInfo, - src: &'a mut T, - ) -> Result { - let beam_width = config - .block_size_search_beam_width - .unwrap_or(config.block_sizes.len() * BSBS_DEFAULT_BEAM_WIDTH_MULTIPLIER); - let mut ret = Self { - config, - stream_info, - src, - beam_width, - best_hyp: None, - current_hyps: vec![], - next_hyps: vec![], - prune_markers: BTreeSet::new(), - }; - ret.extend_one(&None)?; - ret.prune_and_update(); - Ok(ret) - } - - pub fn extend_all(&mut self) -> Result<(), SourceError> { - self.next_hyps.clear(); - let current_hyps = self.current_hyps.clone(); - for hyp in ¤t_hyps { - self.extend_one(&Some(Arc::clone(hyp)))?; - } - self.prune_and_update(); - Ok(()) - } - - pub fn done(&self) -> bool { - self.current_hyps.is_empty() - } - - pub fn results(&self) -> impl Iterator> { - let mut ret = vec![]; - if let Some(best) = self.best_hyp.as_ref() { - let mut cur = Arc::clone(best); - loop { - ret.push(Arc::clone(&cur)); - if let Some(prev) = cur.back_pointer.as_ref() { - cur = Arc::clone(prev); - } else { - break; - } - } - } - ret.into_iter().rev() - } - - fn update_best_hyp(&mut self, hyp: Arc) { - let best_bps = self - .best_hyp - .as_ref() - .map_or(f64::MAX, |h| h.bits_per_sample()); - if hyp.bits_per_sample() < best_bps { - self.best_hyp = Some(hyp); - } - } - - fn extend_one(&mut self, back_pointer: &Option>) -> Result<(), SourceError> { - for &bs in &self.config.block_sizes { - let hyp = Hyp::new( - self.src, - bs, - self.config, - self.stream_info, - back_pointer.clone(), - )?; - if hyp.is_last { - self.update_best_hyp(Arc::clone(&hyp)); - } else { - self.next_hyps.push(hyp); - } - } - Ok(()) - } - - fn prune_and_update(&mut self) { - self.next_hyps.sort_by(|x, y| { - x.bits_per_sample() - .partial_cmp(&y.bits_per_sample()) - .unwrap() - }); - self.prune_markers.clear(); - self.current_hyps.clear(); - for hyp in &self.next_hyps { - if self.prune_markers.contains(&hyp.next_offset()) { - continue; - } - self.prune_markers.insert(hyp.next_offset()); - self.current_hyps.push(Arc::clone(hyp)); - } - self.current_hyps.truncate(self.beam_width); - } -} - -/// Searches combination of block sizes and encodes `src` in variable length format. -/// -/// # Errors -/// -/// This function returns `SourceError` when it failed to read samples from `src`. -#[cfg(feature = "experimental")] -#[allow(clippy::missing_panics_doc)] -pub fn encode_with_multiple_block_sizes( - config: &config::Encoder, - mut src: T, -) -> Result { - let mut stream = Stream::new(src.sample_rate(), src.channels(), src.bits_per_sample()); - let stream_info = stream.stream_info(); - let mut beam_search = BeamSearch::new(config, stream_info, &mut src)?; - - // TODO: MD5 checksums are not supported in BSBS mode. - while !beam_search.done() { - beam_search.extend_all()?; - } - for hyp in beam_search.results() { - stream.add_frame(hyp.frame.clone()); - } - stream.stream_info_mut().set_total_samples(src.len()); - - Ok(stream) -} - -#[cfg(not(feature = "experimental"))] -#[allow(unused_mut, clippy::missing_errors_doc)] -pub fn encode_with_multiple_block_sizes( - _config: &config::Encoder, - mut _src: T, -) -> Result { - unimplemented!("Multiple block-size is only supported when flacenc is built with \"experimental\" feature enabled.") -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/config.rs b/src/config.rs index a71b349..ee2bc62 100644 --- a/src/config.rs +++ b/src/config.rs @@ -34,8 +34,6 @@ use super::lpc::Window; pub struct Encoder { /// The possible block sizes encoder can use. pub block_sizes: Vec, - /// Beam width for block-size search. - pub block_size_search_beam_width: Option, /// Whether encoder runs on multi-thread mode. pub multithread: bool, /// Configuration for stereo-coding module. @@ -51,7 +49,6 @@ impl Default for Encoder { stereo_coding: StereoCoding::default(), subframe_coding: SubFrameCoding::default(), block_sizes: vec![4096usize], - block_size_search_beam_width: None, multithread: cfg!(feature = "par"), } } @@ -65,16 +62,10 @@ impl Verify for Encoder { "Must specify at least one block size.", )); } - if !cfg!(feature = "experimental") && self.block_sizes.len() > 1 { + if self.block_sizes.len() > 1 { return Err(VerifyError::new( "block_sizes", - "Multiple blocksize mode is only allowed when \"experimental\" feature is enabled.", - )); - } - if self.block_size_search_beam_width == Some(0) { - return Err(VerifyError::new( - "block_size_search_beam_width", - "Must be more than 1.", + "Multiple blocksize mode is not supported currently.", )); } for (i, &bs) in self.block_sizes.iter().enumerate() { diff --git a/src/constant.rs b/src/constant.rs index c60f3f0..a26a632 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -21,9 +21,6 @@ pub enum ExitCode { InvalidConfig = -1, } -/// Default block-size beam-search width in factor of #choices. -pub const BSBS_DEFAULT_BEAM_WIDTH_MULTIPLIER: usize = 2; - /// Maximum length of a block. pub const MIN_BLOCKSIZE_SUPPORTED: usize = 32; diff --git a/testtool/reporter.py b/testtool/reporter.py index 7e591d5..38d3589 100644 --- a/testtool/reporter.py +++ b/testtool/reporter.py @@ -37,7 +37,6 @@ "default": [], "st": ["-c", "report/st.config.toml"], "dmse": ["-c", "report/dmse.config.toml"], - "bsbs": ["-c", "report/bsbs.config.toml"], "mae": ["-c", "report/mae.config.toml"], } REFERENCE_BINPATH = "flac-1.3.4/src/flac/flac"