puremp3 0.1.0

MP3 decoding in pure Rust
Documentation
use crate::tables::{
    INTENSITY_STEREO_RATIOS, LFS_INTENSITY_STEREO_RATIOS, SCALE_FACTOR_BAND_INDICES,
};
use crate::types::{BlockType, FrameHeader, GranuleSideInfo, MainDataGranule, MpegVersion};
use std::f32::consts::FRAC_1_SQRT_2;

pub fn stereo(
    header: &FrameHeader,
    side_info: &GranuleSideInfo,
    intensity_stereo: bool,
    mid_side_stereo: bool,
    main_data: &mut MainDataGranule,
) {
    if mid_side_stereo {
        let max_pos = u32::max(main_data.channels[0].count1, main_data.channels[1].count1) as usize;

        for i in 0..max_pos {
            let left = (main_data.channels[0].samples[i] + main_data.channels[1].samples[i])
                * FRAC_1_SQRT_2;
            let right = (main_data.channels[0].samples[i] - main_data.channels[1].samples[i])
                * FRAC_1_SQRT_2;
            main_data.channels[0].samples[i] = left;
            main_data.channels[1].samples[i] = right;
        }
    }

    if intensity_stereo {
        let band_indices = &SCALE_FACTOR_BAND_INDICES[header.sample_rate_table];
        let block_type = side_info.channels[0].block_type;
        if block_type == BlockType::Short || block_type == BlockType::Mixed {
            if block_type == BlockType::Mixed {
                for sfb in 0..8 {
                    if band_indices.0[sfb] >= main_data.channels[1].count1 {
                        stereo_instensity_long(
                            header,
                            side_info.channels[0].scalefac_compress,
                            sfb,
                            main_data,
                        );
                    }
                }

                for sfb in 3..12 {
                    if band_indices.1[sfb] * 3 >= main_data.channels[1].count1 {
                        stereo_instensity_short(
                            header,
                            side_info.channels[0].scalefac_compress,
                            sfb,
                            main_data,
                        );
                    }
                }
            } else {
                for sfb in 0..12 {
                    if band_indices.1[sfb] * 3 >= main_data.channels[1].count1 {
                        stereo_instensity_short(
                            header,
                            side_info.channels[0].scalefac_compress,
                            sfb,
                            main_data,
                        );
                    }
                }
            }
        } else {
            for sfb in 0..21 {
                if band_indices.0[sfb] >= main_data.channels[1].count1 {
                    stereo_instensity_long(
                        header,
                        side_info.channels[0].scalefac_compress,
                        sfb,
                        main_data,
                    );
                }
            }
        }
    }
}

fn stereo_instensity_long(
    header: &FrameHeader,
    scalefac_compress: u16,
    sfb: usize,
    main_data: &mut MainDataGranule,
) {
    let band_indices = &SCALE_FACTOR_BAND_INDICES[header.sample_rate_table];
    let pos = main_data.channels[0].scalefac_l[sfb] as usize;
    let ratio_l;
    let ratio_r;

    let sfb_start = band_indices.0[sfb] as usize;
    let sfb_end = band_indices.0[sfb + 1] as usize;
    if pos != 7 {
        if header.version != MpegVersion::Mpeg1 {
            let i = (sfb >> 1) << (scalefac_compress as usize & 1);
            if sfb & 1 == 0 {
                ratio_l = 1.0;
                ratio_r = LFS_INTENSITY_STEREO_RATIOS[i];
            } else {
                ratio_l = LFS_INTENSITY_STEREO_RATIOS[i];
                ratio_r = 1.0;
            }
        } else if pos == 6 {
            ratio_l = 1.0;
            ratio_r = 0.0;
        } else {
            ratio_l = INTENSITY_STEREO_RATIOS[pos][0];
            ratio_r = INTENSITY_STEREO_RATIOS[pos][1];
        }

        for i in sfb_start..sfb_end {
            let left = ratio_l * main_data.channels[0].samples[i];
            let right = ratio_r * main_data.channels[0].samples[i];
            main_data.channels[0].samples[i] = left;
            main_data.channels[1].samples[i] = right;
        }
    }
}

fn stereo_instensity_short(
    header: &FrameHeader,
    scalefac_compress: u16,
    sfb: usize,
    main_data: &mut MainDataGranule,
) {
    let band_indices = &SCALE_FACTOR_BAND_INDICES[header.sample_rate_table];
    let window_len = (band_indices.1[sfb + 1] - band_indices.1[sfb]) as usize;

    let mut ratio_l: f32;
    let mut ratio_r: f32;

    for win in 0..3 {
        let is_pos = main_data.channels[0].scalefac_s[sfb][win] as usize;
        let sfb_start = band_indices.1[sfb] as usize * 3 + window_len * win;
        let sfb_end = sfb_start + window_len;
        if is_pos != 7 {
            if header.version != MpegVersion::Mpeg1 {
                let i = (sfb >> 1) << (scalefac_compress as usize & 1);
                if sfb & 1 == 0 {
                    ratio_l = 1.0;
                    ratio_r = LFS_INTENSITY_STEREO_RATIOS[i];
                } else {
                    ratio_l = LFS_INTENSITY_STEREO_RATIOS[i];
                    ratio_r = 1.0;
                }
            } else if is_pos == 6 {
                ratio_l = 1.0;
                ratio_r = 0.0;
            } else {
                ratio_l = INTENSITY_STEREO_RATIOS[is_pos][0];
                ratio_r = INTENSITY_STEREO_RATIOS[is_pos][1];
            }

            for i in sfb_start..sfb_end {
                let left = ratio_l * main_data.channels[0].samples[i];
                let right = ratio_r * main_data.channels[0].samples[i];
                main_data.channels[0].samples[i] = left;
                main_data.channels[1].samples[i] = right;
            }
        }
    }
}