C++ 在给定时间内将频率从f1缓慢上升到f2的正弦波
我正在写一个c程序来生成一个正弦波,在给定的时间间隔内,它会慢慢地将频率从f1上升到f2 我已经写了这个c程序,将频率从0提高到10赫兹,但问题是频率在完成360度后会发生变化。如果我尝试在0和360度之间更改频率,则过渡不是平滑的,而是突然的 这是我用的方程,sin,y=振幅*sin(频率*相位)C++ 在给定时间内将频率从f1缓慢上升到f2的正弦波,c++,c,algorithm,math,waveform,C++,C,Algorithm,Math,Waveform,我正在写一个c程序来生成一个正弦波,在给定的时间间隔内,它会慢慢地将频率从f1上升到f2 我已经写了这个c程序,将频率从0提高到10赫兹,但问题是频率在完成360度后会发生变化。如果我尝试在0和360度之间更改频率,则过渡不是平滑的,而是突然的 这是我用的方程,sin,y=振幅*sin(频率*相位) intmain(intargc,char*argv[]){ 双y,频率,相位; int count;//为了便于在matlab中绘制,所有波都在x轴上传播。 对于(频率=0;频率
intmain(intargc,char*argv[]){
双y,频率,相位;
int count;//为了便于在matlab中绘制,所有波都在x轴上传播。
对于(频率=0;频率<10;频率+=1){
对于(相位=0;相位<360;相位++){//相位为360度
y=3*sin(计数*6.283185)+(频率*(相位*(3.14159/180));
printf(“%f%f%f\n”,频率,相位,y);
}
计数++;
}
返回退出成功;
}
线性啁啾的傅里叶变换本身就是一个线性啁啾,所以可能不是。它应该相当简单。与其考虑改变频率,不如考虑让物体旋转得越来越快。它经过的角距离在N秒后可能是X,但在2N秒后会超过2X(可能是4X)。因此,提出一个角距离的公式(例如,alpha=k1*T+k2*T**2),并取该角距离的正弦值,以找到任意时间T的波形值。如果您希望角频率(w=2pi f)随时间线性变化,则
dw/dt=a
和w=w0+(wn-w0)*T/tn(其中,t
从0到tn
,w
从w0
到wn
)。相位是其积分,因此相位=w0t+(wn-w0)*t^2/(2tn)
(如奥利所说):
顺便说一句,如果你在听这个(或者看着它——任何涉及人类感知的东西),我怀疑你不想要线性增长,而是指数增长。但那是…+(void)appendChirp:(int[])样本数据大小:(int)len
带起始频率:(双)带结束频率的启动请求:(双)结束频率
withGain:(双)增益{
双采样器=44100.0;
对于(int i=0;i
fantastic!!效果很好。当n_步长非常大时,相位-=2*PI几乎为零,因此sin(0)是0。相位-=2*PI导致正弦波以负值开始。当while循环被注释掉时,上面的图表是正确的。你能告诉我你读到这篇文章的来源吗。我在这几天头发都松了,你救了我一命。非常感谢。我读到了关于指数增长的文章,但不明白。我可能会问你直观地解释。修复了c代码中的(浮点)问题,谢谢。我不理解关于phase的注释,但它只是在你希望它始终在0-2PI范围内的情况下出现。我没有在任何地方读到它-我只是解决了它-但据我所知,它与wikipedia条目相同(我链接到它,稍后检查)还有,你可以做一个更直接的计算,而不是重复减法。比如int n=phase/(2*PI);phase-=n*2*PI
@andrew cooke你是对的,我不理解while循环。实现while循环的另一种方法是'phase=fmod(phase,(2*PI));'yup(不确定fmod是否存在tbh)。要生成所需Hz的“真实”正弦波频率,请使用计数器和计时器。使用sin公式,生成的频率取决于程序执行的速度。不完全如此。虽然这是平滑的,而且“看起来不错”在图形计算器上,一个快速演示就足以说明错误。使用此代码生成一个由起始频率和结束频率声音包围的声音表明它没有在正确的位置结束。正弦(startFreq,1秒)、扫频(startFreq,endFreq,1秒)、正弦(endFreq,1秒),然后,如果您愿意,执行一些光谱分析。我的光谱分析(酷编辑Pro 2)显示频率高达650赫兹左右。当你的光谱分析显示为650赫兹时,你的输入是什么?我的函数可能不准确,但我很确定它的输出取决于它的输入。顺便说一句,这个方法来自我的软件合成器,听起来不错,看起来也不错。@MusicGenesis对不起,我忘了告诉你了参数!我做了一个从220到440赫兹的正弦扫描。正如我所说,在440赫兹的正弦信号播放之前,扫描在650赫兹左右结束。
int main(int argc, char *argv[]) {
double y, freq,phase;
int count; // for convenience of plotting in matlab so all the waves are spread on x axis.
for (freq = 0; freq < 10; freq+=1) {
for (phase = 0; phase < 360; phase++) { // phase is 360 degrees
y = 3 * sin((count*6.283185)+(freq*(phase*(3.14159/180))));
printf("%f %f %f \n", freq, phase, y);
}
count++;
}
return EXIT_SUCCESS;
}
void sweep(double f_start, double f_end, double interval, int n_steps) {
for (int i = 0; i < n_steps; ++i) {
double delta = i / (float)n_steps;
double t = interval * delta;
double phase = 2 * PI * t * (f_start + (f_end - f_start) * delta / 2);
while (phase > 2 * PI) phase -= 2 * PI; // optional
printf("%f %f %f", t, phase * 180 / PI, 3 * sin(phase));
}
}
from math import pi, sin
def sweep(f_start, f_end, interval, n_steps):
for i in range(n_steps):
delta = i / float(n_steps)
t = interval * delta
phase = 2 * pi * t * (f_start + (f_end - f_start) * delta / 2)
print t, phase * 180 / pi, 3 * sin(phase)
sweep(1, 10, 5, 1000)
+ (void) appendChirp:(int[])sampleData size:(int)len
withStartFrequency:(double)startFreq withEndFrequency:(double)endFreq
withGain:(double)gain {
double sampleRate = 44100.0;
for (int i = 0; i < len; i++) {
double progress = (double)i / (double)len;
double frequency = startFreq + (progress * (endFreq - startFreq));
double waveLength = 1.0 / frequency;
double timePos = (double)i / sampleRate;
double pos = timePos / waveLength;
double val = sin(pos * 2.0 * M_PI); // -1 to +1
sampleData[i] += (int)(val * 32767.0 * gain);
}
}