2017-07-25 276 views
1

最初,我的项目在使用C#的Windows控制台上制作歌曲时使用了Console.Beep(freq,time);,但它的不可靠性导致了desyncs。正弦波点击Beep.BeepBeep

我改为使用Beep Beep类。问题在于,在播放基线时,每个音符的末尾都会有一个可听见的咔嗒声。这是一个example。只用一个音符就没有问题,但连续多次音符都是无法忍受的。

即使我在波形编辑器中打开它,无论我在哪里剪切它,它总是被点击。

我该如何摆脱这种点击,而无需在我的C#控制台项目中安装任何庞大的库?

+0

好故事。你的问题是什么?;) –

+0

为清晰起见@TotumusMaximus – epicbob57

+0

使用该类,您可以添加淡出 - 在最近的50毫秒内,幅度逐渐变为零?请说在过去的50年里每隔10毫秒就会减幅20%? – AgapwIesu

回答

2

你有没有在最后试图抬高幅度高的声音开始,然后再下来。因此,修改哔哔类,读取的内环......

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年中下降,但您可能需要更改该坡道的样本数量。

+1

这不仅解决了这个问题,而且也是应用[ADSR](https://en.wikipedia.org/wiki/Synthesizer#Attack_Decay_Sustain_Release_.28ADSR.29_envelope)包络曲线的第一步,这将使声音变得很多更有趣.. – TaW

+0

这很有趣,因为我对声学知之甚少,而且我只是在黑暗中拍摄而已。您在评论中提供的ADSR信封上的链接非常有趣。 – AgapwIesu

2

要解释为什么不深入研究数字信号处理理论有点困难,但基本上是由于您的信号具有非常突然的启动和停止而导致的咔哒声,这些咔嗒声会转化为高频成分,并可以作为“点击”发声。

如果您淡入和淡出信号的第一个和最后10%(例如使用Audacity),您会发现点击消失。

+1

另外,他可以确保只切断波形中的[zero-crossing](https://en.wikipedia.org/wiki/Zero_crossing)(以避免褪色,如果不需要) – bassfader

+0

这将是如果我没有制作C#控制台应用程序,可能会有这种可能 – epicbob57

+0

这与它有什么关系?两种方式都只是关于数据幅度。 – TaW

2

更新:我会留下答案,因为基本的想法仍然成立,但同意适用淡出的解决方案。除了解决了点击的问题,这也朝施加ADSR包络线,这将使得纯正弦波第一步听起来更有趣即便是不添加色彩..


问题是与蜂鸣类。它不用在零交叉处结束,即完整的正弦波。

解决这个问题的最自然的方法是控制它创建的样本数量。

不知道这种计算的:

double xx = 2 * Math.PI/Frequency; 
Samples = (int)((int)(Samples * xx)/xx); 

或是被创建之后,你可以截断数据。

你可以试试这个,而粗暴的方式:对4

.. 
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个零是开始(或者说结束)

我相信其他的方法来纠正这个会少的hackish,但它应该对于初学者工作..