Rust Rodio库中意外Frequency Modulation行为问题求助
Rust Rodio库中意外Frequency Modulation行为问题求助
大家好,我在使用Rodio 0.20.1和0.21.0版本时遇到了一个奇怪的调频(FM)行为问题,想请社区的朋友们帮忙排查一下问题所在。
具体情况是这样的:我写了一个自定义的Source实现来生成调频音频,当我把常量DEMONSTRATING_DEFECT设为false时,播放的声音是符合预期的——类似警报器的效果,在两个固定频率之间交替变化;但当把它设为true,使用随时间正弦变化的频率函数时,原本期望的是频率在440Hz±50Hz之间平滑交替,结果实际播放出来的却是高频越来越高,低频越来越低,完全偏离了预期效果。
以下是我的main.rs代码:
use std::{f32::consts::PI, io::stdin}; use rodio::{OutputStream, OutputStreamBuilder, Source}; const SAMPLE_RATE: u32 = 44_100; struct FrequencyModulation { sample_num: u32, frequency: Box<dyn Fn(f32) -> f32 + Send + 'static>, } fn amplitude(time_in_secs: f32, hz: f32) -> f32 /* (-1.0, 1.0) */ { (2.0 * PI * hz * time_in_secs).sin() } fn time(sample_num: u32) -> f32 { sample_num as f32 / SAMPLE_RATE as f32 } impl FrequencyModulation { pub fn new(frequency: Box<dyn Fn(f32) -> f32 + Send + 'static>) -> FrequencyModulation { FrequencyModulation { sample_num: 0, frequency, } } } impl Source for FrequencyModulation { fn current_span_len(&self) -> Option<usize> { None } fn channels(&self) -> u16 { 1 } fn sample_rate(&self) -> u32 { SAMPLE_RATE } fn total_duration(&self) -> Option<std::time::Duration> { None } } impl Iterator for FrequencyModulation { type Item = f32; fn next(&mut self) -> Option<Self::Item> { let time_in_secs = time(self.sample_num); let instantaneous_frequency = (self.frequency)(time_in_secs); let sample = amplitude(time_in_secs, instantaneous_frequency); self.sample_num = self.sample_num + 1; Some(sample) } } const DEMONSTRATING_DEFECT: bool = true; fn main() { let (_stream, stream_handle) = OutputStreamBuilder::open_default_stream().unwrap(); let freq = if DEMONSTRATING_DEFECT { // 行为异常:高频持续升高,低频持续降低 |t: f32| 440.0 + 50.0 * (t * 2.0 * PI).sin() } else { // 行为符合预期:类似警报器的交替音调 |t: f32| 440.0 + if (t * 2.0 * PI).sin() > 0.0 { 50.0 } else { -50.0 } }; let source = FrequencyModulation::new(Box::new(freq)); let _ = stream_handle.mixer().add(source); stdin().read_line(&mut String::new()).unwrap(); }
我怀疑是不是自己对调频的实现逻辑有误解?毕竟直接用瞬时频率计算振幅的方式,是不是忽略了调频需要累积相位而不是直接用当前时间乘以频率?希望有经验的朋友能帮我指出问题所在,或者给出正确的实现思路,谢谢大家!
内容来源于stack exchange
相关产品推荐
相关产品推荐

