生成下降频率的正弦波模式-不可能吗? [英] Generating descending frequency sinewave patterns - Impossible?!

查看:51
本文介绍了生成下降频率的正弦波模式-不可能吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好:)

我正在测试正弦波发生器的应用程序,它可以生成,可视化和播放各种正弦波信号和信号模式.当我尝试生成线性下降频率的正弦波时,我遇到了一个非常奇怪的问题(至少对我而言)(更具体地说:从22Hz开始,下降到8.4Hz).
这是频率调制的一个示例,其中调制信号只是一个简单的线性下降模式.
但是为了准确解释问题所在,我首先必须向您展示我首先要生成具有恒定频率的正弦波信号的方法:

我使用了显而易见的数学方程式:

Amplitude * sin(Time * Frequency + Phase)
(该相位始终为0,因此不包含在实际方程式中)

这是生成正弦波音频信号的功能的简化版本.

Hi All :)

I''m working on my test sinewave generator application wich can generate, visualize and play variety of sinewave signals and signal patterns. I encountered a pretty strange problem (at least for me) when I tried to generate a sinewave with linearly descending frequency (more specifically: starting at 22Hz and descending down to 8.4Hz).
This is an example of frequency modulation where the modulating signal is just a simple linear descending pattern.
But in order to explain exactly what the problem is I have to first show you what my approach is to generate sinewave signal with constant frequency in the first place:

I use the obvious math equation:

Amplitude * sin(Time * Frequency + Phase)
(The phase is not included in the actual equation because it''s always 0)

This is a simplified version of the function that generates sinewave audio signals.

/* RAD() is a macro I use to translate the value given to sin() from degrees into radians as the standard sin() function requires it. This is what allows me to use linear frequency instead of angular.*/
#define RAD(a)	((a) * 0.017453292519943295769236907684886)

void CWAV_ViewerDoc::OnToolsGeneratevoice()
{
	/* Defining the initial parameters of the playable audio signal. */	
	m_waveHeader.nChannels	  = 2;	    // Channels.
	m_waveHeader.nSampPerSec  = 44100;  // Samples per second.
	m_waveHeader.nBytePerSec  = 176400; // Bytes per second (playback speed).
	m_waveHeader.nByteInSamp  = 4;	    // Bytes in sample.
	m_waveHeader.nBitsPerSamp = 16;	    // Bytes per sample.

	/* Defining playback time. (in number of samples) */
	m_nNumSamples = m_waveHeader.nSampPerSec * 60; // 1 minute playback.

	m_puiAudioData = new UINT[m_nNumSamples];

	/* Here I define the factor at which the dTime argument will be progressing through out the track in order to generate 1Hz frequency. */
	double dFactor	= 360.0 / double(m_waveHeader.nSampPerSec); // 1 Hz
	double dTime	= 0.0; // The argument...
	UINT   uiSample;

	for(UINT pos = 0; pos < m_nNumSamples; pos++)
	{
		/* As you can see, since dTime progresses is set at specific rate (for 1Hz) determined by the dFactor simply multiplying it by the required number in hertz produces exactly the desired frequency.*/
		// Amplitude = +/-32767 (as per spec of PCM standard).
		// Frequency = 22Hz
		uiSample = (SHORT)(32767.0 * sin(RAD(dTime * 22.0));
		dTime += dFactor;

		/* Here I copy the value from the lower word to the higher so it'll be the same for both channels and then put it in the buffer. */
		m_puiAudioData[pos] = uiSample << 16 | uiSample & 0x0000ffff;
	}
}



(对我而言)这是生成正弦波信号的最简单,最直接,最直观的方法,它已经过测试,并且效果很好.

现在的问题!现在,我将列出相同的功能,但在算法中添加了降频功能,并且它也非常简单明了.我只是简单地得到22和8.4之间的差,然后将其乘以样本总数,就得出了降频系数,该频率降低的原因是每个周期的频率下降-在这里,它是:



This is (for my mind) the simplest, the most straightforward and intuitive way to generate sinewave signal, it''s tested and it works perfectly.

Now the problem! I''ll now list the same function but with frequency descension added to the algorithm, and it''s also simple and straightforward. I simply get the difference between 22 and 8.4 and devide it by the total number of samples and that gives me the descension factor at which the frequency sould descend every cycle - here it is:

/*With this macro I translate the value given to sin() from degrees into radians as the standard sin() function requires it.*/
#define RAD(a)	((a) * 0.017453292519943295769236907684886)

void CWAV_ViewerDoc::OnToolsGeneratevoice()
{
	/* Defining the initial parameters of the playable audio signal. */	
	m_waveHeader.nChannels	  = 2;	    // Channels.
	m_waveHeader.nSampPerSec  = 44100;  // Samples per second.
	m_waveHeader.nBytePerSec  = 176400; // Bytes per second (playback speed).
	m_waveHeader.nByteInSamp  = 4;	    // Bytes in sample.
	m_waveHeader.nBitsPerSamp = 16;	    // Bytes per sample.

	/* Defining playback time. */
	m_nNumSamples = m_waveHeader.nSampPerSec * 60; // 1 minute playback.

	m_puiAudioData = new UINT[m_nNumSamples];

	/* Here I define the factor at which the dTime argument will be progressing in order to generate 1Hz frequency. */
	double dFactor	= 360.0 / double(m_waveHeader.nSampPerSec); // 1 Hz
	double dTime	= 0.0; // The argument...
	UINT   uiSample;

	/* Here it is the descention factor. */
	double dDescFactor = (22.0 - 8.4) / double(m_nNumSamples);
	double dDescension  = 0.0; // The descension argument...

	for(UINT pos = 0; pos < m_nNumSamples; pos++)
	{
		/* Now you can see how the constant 22.0 is substracted by the argument which is 0.0 at the beginning and gradually increases to 13.6 at the end which substracted from 22.0 gives 8.4 */
	     uiSample = (SHORT)(32767.0 * sin(RAD(dTime * (22.0 - dDescension)));
	     dTime += dFactor;
	     dDescension += dDescFactor;

		/* Here I double the sample value so it'll be the same for both channels and then put it in the buffer. */
		m_puiAudioData[pos] = uiSample << 16 | uiSample & 0x0000ffff;
	}
}



我确信这个例子太简单了,以至于造成理解上的任何困难,而且我认为每个人都同意结果必须是正弦波信号模式,其频率从22Hz下降到8.4Hz-但这是不会发生什么...

实际上,发生的情况是在生成的轨道的前半部分,频率下降的幅度很小(实际上是从高于22Hz的频率开始).在轨道的第二部分,它开始以不断增加的速度下降(这绝对不是线性模式),然后大约在轨道的7/8处形成了所谓的周转率"-在这一点上,相位以180度快速移动,形成"W"字样,然后频率实际上开始上升了!从这一点到结束(在周转频率附近,频率也远低于8.4Hz).

同样,在我试图解决问题的过程中,我发现在这种特殊情况下,周转率"仅仅是一个.如果频率.范围更宽,将出现多个这样的"W"-"M"转换点,并且它们之间的频率上下移动,而所有这些的驱动模式只是从一个正数到另一个正数的线性偏差号.

最后一件事:如果您从该范围内获得任何特定的频率并将其设置为恒定频率. -它会完美地生成!

这整个事情没有任何意义!我几乎不知道如何解决这个难题...

任何帮助将不胜感激!
多谢您阅读这份延长的TC! :)



I''m sure that this example is way too simple to cause any difficulties understanding it, and I think that everybody would agree that the result must be a sinewave signal pattern with frequency descending from 22Hz down to 8.4Hz - but that''s not what happens...

In reality what happens is that in the first half of the generated track the frequency descends very little (and it actually starts from freq. higher than 22Hz). In the second part of the track it starts descending at ever increassing rate (that''s definitely not a linear pattern), and then roughly at 7/8-ths of the track it forms what I could call a "turnover" - it rapidly shifts the phase at 180 degrees forming ''W'' letter like pattern at this point, and then the frequency actualy starts to ascend?! And it does so from that point to the end (also around the turnover the freq. is much lower than 8.4Hz).

Also in my attempts to solve the problem I found that the "turnover" is only one in this particular case. If the freq. range is wider, multiple such ''W'' - ''M'' turnover points will appear and the frequency between them moves up and down, while the driving pattern of all this is only a linear dissension from one positive number to another positive number.

One last thing: If you get any particular frequency from within the range and set it to be generated as constant freq. - it''ll be generated perfectly as it should!

This whole thing does not make any sense! I don''t nearly have any idea on how to solve this mistery...

Any help would be much appreciated!
Thank you for even reading this prolong TC! :)

推荐答案

您不能将绝对时间乘以当前频率.您必须将每个时间片的时间与频率因子相乘.
例如:
You cannot multiply the absolute time by the current frequency. You have to integrate the time for each time slice multiplied by the frequency factor.
For example:
double currAngle = 0;
for(...)
{
  uiSample = (SHORT)(32767.0 * sin(RAD(currAngle));
//dTime += dFactor;
  dDescension += dDescFactor;
  currAngle += dFactor * (22.0 - dDescension);
}


问候.


在我看来,您使用了错误的dFactor(它与频率降低率-和播放持续时间-不符).应该是
In my opinion, you are using the wrong dFactor (it doesn''t match the frequency decreasing rate -and the playback duration-). It should be
dFactor = 1.0/m_waveHeader.nSampPerSec;


这篇关于生成下降频率的正弦波模式-不可能吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆