1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
use rustfft::FFTplanner; use DCTnum; use dct1::*; use dct2::*; use dct3::*; use dct4::*; use mdct::*; /// The DCT planner is used to make new DCT algorithm instances. /// /// RustDCT has several DCT algorithms available for each DCT type; For a given DCT size and type, the FFTplanner /// decides which of the available DCT algorithms to use and then initializes them. /// /// ~~~ /// // Perform a DCT Type 4 of size 1234 /// use rustdct::DCTplanner; /// /// let mut input: Vec<f32> = vec![0f32; 1234]; /// let mut output: Vec<f32> = vec![0f32; 1234]; /// /// let mut planner = DCTplanner::new(); /// let mut dct4 = planner.plan_dct4(1234); /// dct4.process(&mut input, &mut output); /// ~~~ /// /// If you plan on creating multiple DCT instances, it is recommnded to reuse the same planner for all of them. This /// is because the planner re-uses internal data across DCT instances wherever possible, saving memory and reducing /// setup time. (DCT instances created with one planner will never re-use data and buffers with DCT instances created /// by a different planner) /// /// Each FFT instance owns `Arc`s to its shared internal data, rather than borrowing it from the planner, so it's /// perfectly safe to drop the planner after creating DCT instances. pub struct DCTplanner<T> { fft_planner: FFTplanner<T>, } impl<T: DCTnum> DCTplanner<T> { pub fn new() -> Self { Self { fft_planner: FFTplanner::new(false) } } /// Returns a DCT Type 1 instance which processes signals of size `len`. /// If this is called multiple times, it will attempt to re-use internal data between instances pub fn plan_dct1(&mut self, len: usize) -> Box<DCT1<T>> { //benchmarking shows that below about 25, it's faster to just use the naive DCT1 algorithm if len < 25 { Box::new(DCT1Naive::new(len)) } else { let fft = self.fft_planner.plan_fft((len - 1) * 2); Box::new(DCT1ViaFFT::new(fft)) } } /// Returns a DCT Type 2 instance which processes signals of size `len`. ///If this is called multiple times, it will attempt to re-use internal data between instances pub fn plan_dct2(&mut self, len: usize) -> Box<DCT2<T>> { //benchmarking shows that below about 5, it's faster to just use the naive DCT1 algorithm if len < 5 { Box::new(DCT2Naive::new(len)) } else { let fft = self.fft_planner.plan_fft(len); Box::new(DCT2ViaFFT::new(fft)) } } /// Returns a DCT Type 3 instance which processes signals of size `len`. /// If this is called multiple times, it will attempt to re-use internal data between instances pub fn plan_dct3(&mut self, len: usize) -> Box<DCT3<T>> { //benchmarking shows that below about 5, it's faster to just use the naive DCT1 algorithm if len < 5 { Box::new(DCT3Naive::new(len)) } else { let fft = self.fft_planner.plan_fft(len); Box::new(DCT3ViaFFT::new(fft)) } } /// Returns a DCT Type 4 instance which processes signals of size `len`. /// If this is called multiple times, it will attempt to re-use internal data between instances pub fn plan_dct4(&mut self, len: usize) -> Box<DCT4<T>> { //benchmarking shows that below about 100, it's faster to just use the naive DCT4 algorithm if len < 100 { Box::new(DCT4Naive::new(len)) } else { let fft = self.fft_planner.plan_fft(len * 4); Box::new(DCT4ViaFFT::new(fft)) } } /// Returns a MDCT instance which processes inputs of size ` len * 2` and produces outputs of size `len`. /// /// `window_fn` is a function that takes a `size` and returns a `Vec` containing `size` window values. /// See the [`window_fn`](mdct/window_fn/index.html) module for provided window functions. /// /// If this is called multiple times, it will attempt to re-use internal data between instances pub fn plan_mdct<F>(&mut self, len: usize, window_fn: F) -> Box<MDCT<T>> where F: Fn(usize) -> Vec<T>, { //benchmarking shows that using the inner dct4 algorithm is always faster than computing the naive algorithm let inner_dct4 = self.plan_dct4(len); Box::new(MDCTViaDCT4::new(inner_dct4, window_fn)) } /// Returns an IMDCT instance which processes input of size `len` and produces outputs of size `len * 2`. /// /// `window_fn` is a function that takes a `size` and returns a `Vec` containing `size` window values. /// See the [`window_fn`](mdct/window_fn/index.html) module for provided window functions. /// /// If this is called multiple times, it will attempt to re-use internal data between instances pub fn plan_imdct<F>(&mut self, len: usize, window_fn: F) -> Box<IMDCT<T>> where F: Fn(usize) -> Vec<T>, { //benchmarking shows that using the inner dct4 algorithm is always faster than computing the naive algorithm let inner_dct4 = self.plan_dct4(len); Box::new(IMDCTViaDCT4::new(inner_dct4, window_fn)) } }