问题描述
我从 Google 的文本到语音服务中获取 16 位 PCM 数据(24000 Hz),然后将其存储在 u8 数组中。有没有一种简单的方法可以将其重新采样到 48000 Hz,输出为 u8 阵列?我不明白 FFmpeg 上的任何在线示例。
现在我将它包裹在一个 Cursor 中以单独读取每个 i16,然后将每个 i16 复制一次(即,使 1234 变为 11223344)。我的逻辑是,既然原始音频是 24000,那么加倍就是 48000,对吗?
let mut raw = Cursor::new(raw);
let mut new_samples = Vec::new();
loop {
match raw.read_i16::<LittleEndian>() {
Ok(x) => {
samples.push(x);
samples.push(x);
}
Err(_) => break,}
}
接下来我使用 hound crate 将新样本转换为 48000 WAV。
let mut new_wav = Cursor::new(Vec::new());
let mut writer = WavWriter::new(
&mut new_wav,WavSpec {
channels: 1,sample_rate: 48000,bits_per_sample: 16,sample_format: SampleFormat::Int,},)
.unwrap();
new_samples
.into_iter()
.for_each(|x| writer.write_sample(x).unwrap());
writer.finalize().unwrap();
现在 new_wav 应该有 48000 Hz 的音频。但这不起作用。当我使用 discord songbird crate 播放它时,我只听到一个非常简短的静电:
call.lock().await.play_source(Input::new(
false,new_wav.into_inner().into(),Codec::Pcm,Container::Raw,None,));
解决方法
好的,我想通了。我就是这样做的。
let mut original = Cursor::new(original);
let mut resampled = Cursor::new(Vec::new());
loop {
match original.read_i16::<LittleEndian>() {
Ok(x) => {
// Write it twice
resampled.write_i16::<LittleEndian>(x).unwrap();
resampled.write_i16::<LittleEndian>(x).unwrap();
}
Err(_) => break,}
}
现在“重新采样”为 48000 Hz(并且播放完美)。