use std::{i16, num::NonZeroUsize};
use clap::Parser;
use fixed_resample::{FixedResampler, LastPacketInfo, ResampleQuality};
use hound::SampleFormat;
const MAX_CHANNELS: usize = 2;
#[derive(Parser)]
struct Args {
path: std::path::PathBuf,
target_sample_rate: u32,
quality: String,
}
pub fn main() {
let args = Args::parse();
let quality = match args.quality.as_str() {
"low" => ResampleQuality::Low,
"high" => ResampleQuality::High,
s => {
eprintln!("unkown quality type: {}", s);
println!("Valid options are [\"low\", and \"high\"]");
return;
}
};
let mut reader = match hound::WavReader::open(&args.path) {
Ok(r) => r,
Err(e) => {
eprintln!("Failed to open file: {}", e);
return;
}
};
let spec = reader.spec();
if spec.sample_format != SampleFormat::Int || spec.sample_format != SampleFormat::Int {
eprintln!("Only wav files with 16 bit sample formats are supported in this example.");
return;
}
if spec.sample_rate == args.target_sample_rate {
println!("Already the same sample rate.");
return;
}
if spec.channels as usize > MAX_CHANNELS {
eprintln!(
"Only wav files with up to {} channels are supported in this example.",
MAX_CHANNELS
);
}
let num_channels = NonZeroUsize::new(spec.channels as usize).unwrap();
let in_samples: Vec<f32> = reader
.samples::<i16>()
.map(|s| s.unwrap() as f32 / (i16::MAX as f32))
.collect();
let mut resampler = FixedResampler::<f32, MAX_CHANNELS>::new(
num_channels,
spec.sample_rate,
args.target_sample_rate,
quality,
true, );
let input_frames = in_samples.len() / num_channels.get();
let output_frames = resampler.out_alloc_frames(input_frames as u64) as usize;
let mut out_samples = Vec::new();
out_samples.reserve_exact(output_frames * num_channels.get());
resampler.process_interleaved(
&in_samples,
|data| {
out_samples.extend_from_slice(data);
},
Some(LastPacketInfo {
desired_output_frames: Some(output_frames as u64),
}),
true, );
let mut new_file = args.path.clone();
let file_name = args.path.file_stem().unwrap().to_str().unwrap();
new_file.set_file_name(format!("{}_res_{}.wav", file_name, args.target_sample_rate));
let new_spec = hound::WavSpec {
channels: spec.channels,
sample_rate: args.target_sample_rate,
bits_per_sample: 16,
sample_format: hound::SampleFormat::Int,
};
let mut writer = match hound::WavWriter::create(new_file, new_spec) {
Ok(w) => w,
Err(e) => {
eprintln!("Failed to create file: {}", e);
return;
}
};
for &s in out_samples.iter() {
writer.write_sample((s * i16::MAX as f32) as i16).unwrap();
}
writer.finalize().unwrap();
}