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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use clap::Parser;
use fixed_resample::{
audioadapter_buffers::direct::InterleavedSlice, Interleaved, LastPacketInfo, PacketResampler,
ResampleQuality, ResamplerConfig,
};
use hound::SampleFormat;
#[derive(Parser)]
struct Args {
/// The path to the audio file to play
path: std::path::PathBuf,
/// The target sample rate.
target_sample_rate: u32,
/// The resample quality. Valid options are ["very_low", "low", "high", and "high_with_low_latency"].
quality: String,
}
pub fn main() {
let args = Args::parse();
let quality = match args.quality.as_str() {
"very_low" => ResampleQuality::VeryLow,
"low" => ResampleQuality::Low,
"high" => ResampleQuality::High,
"high_with_low_latency" => ResampleQuality::HighWithLowLatency,
s => {
eprintln!("unkown quality type: {}", s);
println!("Valid options are [\"very_low\", \"low\", \"high\", and \"high_with_low_latency\"]");
return;
}
};
// --- Load the audio file with hound ----------------------------------------------------
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;
}
let num_channels = spec.channels as usize;
let in_samples: Vec<f32> = reader
.samples::<i16>()
.map(|s| s.unwrap() as f32 / (std::i16::MAX as f32))
.collect();
// --- Resample the contents into the output ---------------------------------------------
let mut resampler = PacketResampler::<f32, Interleaved<f32>>::new(
num_channels,
spec.sample_rate, // input sample rate
args.target_sample_rate, // output sample rate
ResamplerConfig {
quality,
..Default::default()
},
);
// Allocate an output buffer with the needed number of frames.
let input_frames = in_samples.len() / num_channels;
let output_frames = resampler.out_alloc_frames(input_frames as u64) as usize;
let mut out_samples = Vec::new();
// Since we know we don't need any more samples than this, it's typically a
// good idea to try and save memory by using `reserve_exact`.
out_samples.reserve_exact(output_frames * num_channels);
// Resample to the output buffer. This method is realtime-safe.
resampler.process(
// The input buffer. You can use one of the types in `fixed_resample::audioadapter_buffers::::*` to
// wrap your buffer into a type that implements `Adapter`.
&InterleavedSlice::new(&in_samples, num_channels, input_frames).unwrap(),
None, // input range
None, // active channels mask
// This method gets called whenever there is a new packet of resampled data.
|data, _frames| {
out_samples.extend_from_slice(data);
},
// Whether or not this is the last (or only) packet of data that
// will be resampled. This ensures that any leftover samples in
// the internal resampler are flushed to the output.
Some(LastPacketInfo {
// Let the resampler know that we want an exact number of output
// frames. Otherwise the resampler may add extra padded zeros
// to the end.
desired_output_frames: Some(output_frames as u64),
}),
// Trim the padded zeros at the beginning introduced by the internal
// resampler.
true, // trim delay
);
// --- Write the resampled data to a new wav file ----------------------------------------
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();
}