最初,我使用C#在Windows控制台中制作一首歌的项目使用Console.Beep(freq,time);
,但它的不可靠性导致了desyncs。
我改为使用Beep Beep类。问题是,在播放基线时,每个音符的末尾都会发出咔嗒声。这是example。只用一张纸条就可以了,但是连续多张纸条让人感到无法忍受。
即使我在波形编辑器中打开它,无论我在哪里裁剪它,它总是点击。
如何在不将任何庞大的库安装到我的C#控制台项目中的情况下摆脱这种点击?
答案 0 :(得分:2)
有点难以解释为什么不深入研究数字信号处理理论,但基本上是因为你的信号具有非常突然的启动和停止而导致的咔嗒声转换成可以听到的高频分量&# 39;单击'
如果淡入和淡出信号的第一个和最后一个10%(例如使用Audacity),您会发现点击消失。
答案 1 :(得分:2)
更新:我会留下答案,因为基本的想法仍然存在,但同意应用淡出的解决方案。除了解决点击问题之外,这也是应用ADSR包络曲线的第一步,即使不添加泛音也会使纯正弦波听起来更有趣。
问题在于Beep类。它没有注意在零交叉上结束,即在完整的正弦波上结束。
最正确的方法是控制它创建的样本数量。
不确定此计算:
double xx = 2 * Math.PI / Frequency;
Samples = (int)( (int)(Samples * xx) / xx);
或者您可以在创建数据后截断数据。
你可以尝试这种粗暴的方式:
..
MS.Seek(0, SeekOrigin.Begin);
byte[] bytes = MS.ToArray();
Array.Reverse(bytes);
int z = 0;
for (int i = 0; i < bytes.Length; i+=4)
{
int v = bytes[i] + bytes[i+1] + bytes[i+2] + bytes[i+3];
if (v == 0) { z = i; break; }
}
MS.SetLength(bytes.Length - z);
..
这会找到流中的最后一个过零点,即在4的倍数上开始(或者更确切地说)结束的最后连续4个零。
我确定其他方法可以解决这个问题,但这种做法不会那么严厉,但它应该适合初学者。
答案 2 :(得分:2)
您是否尝试在声音开始时将振幅提升,然后在结束时再次降低振幅。因此,修改那个beep beep类的内部循环,它读取...
for (int T = 0; T < Samples; T++)
{
short Sample = System.Convert.ToInt16(A * Math.Sin(DeltaFT * T));
BW.Write(Sample);
BW.Write(Sample);
}
可以修改为此
for (int T=0; T < Samples; T++)
{
double AmpRamp = 1.0D;
if (T<1000) {
AmpRamp = ((double) T) / 1000.0D;
} else if (T > Samples - 1000) {
AmpRamp = ((double) (Samples - T)) / 1000.0D;
}
short Sample = System.Convert.ToInt16(A*AmpRamp*Math.Sin(DeltaFT * T));
BW.Write(Sample);
BW.Write(Sample);
}
这会增加前1000个样本的幅度,然后在最后1000个样本中逐渐减小,但您可能需要更改斜坡的样本数量。