目录
1. 简介
该代码也可在https://github.com/amarnaths0005/SineSum2上可用
您可以在SineSum2上在线使用它。
在电气工程的本科课程中,学生会遇到寻找正弦值总和的问题。虽然有些学生发现理解这个概念很容易,但其他一些学生发现它并不容易。SineSum是一个程序,它通过视觉辅助工具帮助学生理解正弦的总和,以查看当不同的振幅和相位变化时事物如何变化。
吸引我的课程之一是斯坦福工程无处不在的傅里叶变换课程。在第二课中,教授介绍了SineSum程序,这是一个可视化正弦和的Matlab程序。我最近开始了学习HTML5技术(HTML,CSS和Javascript)的旅程,并认为用HTML5重写基于Matlab的SineSum程序是个好主意,这样它就可以在浏览器上运行。这个应用程序是进入HTML5之旅的结果。
2. 正弦数和
当许多不同振幅和相位的基于正弦的表达式相加(也称为叠加)时,结果是正弦的总和。由于振幅值为A的正弦值范围从-A到+A,因此叠加两个正弦值并不类似于简单地添加它们的振幅。振幅、相位和频率以不那么简单的方式组合在一起,得出结果总和。正是这个正弦的总和,这个应用程序使人能够可视化。正弦的总和定义为总和
其中A k是不同的振幅,φk是不同的相位。单个分量称为谐波;例如,涉及A3和φ3的成分构成三次谐波。该总和中的谐波总数为N,t 是时间变量。在我们的例子中,N是10,更明确地表示的总和是:
换句话说,此HTML5应用程序计算前十次谐波的总和,允许用户改变各个幅度和相位。用户可以可视化单个谐波的轮廓,以及正弦的总和。还显示了3D光谱图。下面给出了Chrome上该应用程序的屏幕截图。
在屏幕顶部,用户选择需要指定幅度和相位的谐波数,并使用顶部的滑块控件改变该幅度和相位。随着这些幅度和相位值的修改,表中的相应行也会相应修改,下面的三个图表也会动态变化。光谱剖面图将这些幅度和相位值显示为3D图。当前正在修改的谐波波形显示在表格下方的中间图中。表格最右边的图表显示了正弦的总和,即十个谐波叠加的结果。单击顶部的“播放声音”按钮可播放与当前振幅和相位集相对应的声音。
在本文的其余部分,我们将介绍实现此结果的软件方面。
3. 更详细的要求
在本文的这一部分中,将更详细地介绍要求。下图列出了HTML格式的GUI元素的ID,软件要求显示在图后的表中。
用户操作 | 应用程序功能 |
用户更改opHarmonic选项框中的谐波数。 |
|
用户更改范围滑块raAmpl中的值。 |
|
用户更改范围滑块raPhase中的值。 |
|
用户单击表格tblHarmonic的一行。 |
|
用户单击“播放声音”按钮。 |
|
用户单击“重置值”按钮。 |
|
4. 编码方面
与大多数HTML5应用程序一样,该软件有三个部分——HTML部分,CSS部分和JavaScript部分。HTML和CSS部分在这个应用程序中非常简单;检查这些文件是一个简单的练习。我们在这里提供了更多关于JavaScript部分的解释。一小部分代码也使用JQuery。
4a. 重要变量
十次谐波的幅度和相位值存储在几个数组中,如下所示:
var sineSum = 0.0;
for (var j = 0; j < numberOfHarmonics; ++j){
var val1 = 2 * Math.PI * (j + 1) * tVal + phaseArray[j];
var val2 = amplitudeArray[j] * Math.sin(val1);
sineSum += val2;
}
有一个称为currentHarmonic内部变量,用于存储用户参数变化的当前谐波的值。将上述两个数组中的20个值组合在一起以创建另一个名为sineSumValuestVal的数组,该数组用于生成显示正弦和的图。对于时间变量的特定值,正弦和的计算如下代码摘录:
var sineSum = 0.0;
for (var j = 0; j < numberOfHarmonics; ++j){
var val1 = 2 * Math.PI * (j + 1) * tVal + phaseArray[j];
var val2 = amplitudeArray[j] * Math.sin(val1);
sineSum += val2;
}
4b.在显示2D图形的画布上绘图
此应用程序中有两个显示2D图形的画布;这些是canvas01和canvas02。在这些画布中,图形的x维度显示时间。在这两个画布上绘制如下:
- 绘制图形的外框以及网格。这是在名为drawGraphBox()的函数中完成的。此函数还会绘制这两个画布中的一些文本内容。
- 然后是绘制实际曲线的部分。为此,持续时间为2秒的时间维度分为400个时间时刻。对于这些时间时刻中的每一个,将计算纵坐标值,并在一系列lineTo()画布函数调用中绘制图形,然后进行一次moveTo()调用。请注意确保绘制的图形是直立的,因为画布坐标系的y轴指向下方。
- 要使外观呈现动画,请在每次绘制调用之前使用context.clearRect()清除画布。
- 特定于正在绘制的画布的更多标签将添加到画布中。
例如,线条的绘制是在此代码提取中完成的:
xPoint0 = xMarginLeft;
yPoint0 = (sineVals[0] - yMin) * yFactor + yLim1;
context01.moveTo(xPoint0, yPoint0);
for( var i = 1; i < sineSumValues.length; ++i) {
xPoint1 = xMarginLeft + i * xStep;
yPoint1 = (sineVals[i] - yMin) * yFactor + yLim1;
context01.lineTo(xPoint1, yPoint1);
}
4c.在画布上绘制显示3D图形
这与canvas canvas03中的绘图有关。最初,我想使用WebGL绘制3D图形;并开始踏上学习WebGL的旅程。但是,在更仔细地查看斯坦福工程无处不在——傅里叶变换网站上提供的SineSum2 Matlab应用程序中的图形时,我觉得可以巧妙地使用简单的2D图形调用来创建3D效果。
- 外部边界框只是一个线框,并使用画布moveTo()和lineTo()函数调用绘制为一组八条线。这伴随着网格的绘制以增强3D效果。
- 在频谱图中,每个谐波都由一个表示其幅度和相位的点表征。利用我在基本向量代数方面的知识,我定义了三个向量,而不是三个方向——谐波、相位和振幅各一个。一旦定义了这些方向,为每个光谱点绘制线条就变成了一个简单的练习。
- 为了给人一种谱线位于盒子内的感觉,在绘制谱线之前绘制了外边界框的一些线,随后绘制了其他线;这样就定义了z顺序,给人一种3D的感觉。
- 和以前一样,为了给人一种动画的感觉,在绘制之前会使用context.clearRect()清除画布区域。
4d.播放声音
我们使用Web音频API来生成声音。这涉及创建音频上下文,然后创建对应于振幅和相阵的周期波。感谢CP成员M. R. van Mourik的建议,并在本文的评论中包含相关代码。
早些时候,我使用了GitHub上提供的Riffwave项目。此后,该项目中的Web Audio API取代了此功能。
您可能会注意到Matlab生成的声音与此应用程序生成的声音不同。我不知道Matlab产生声音的方式。您会发现使用不同的振幅和相位会产生不同种类的声音,这是预期的行为。
4e.代码的其他方面
- 我没有为此应用程序使用任何框架(我仍然是一个学习者),您可能会发现代码是普通的。除了JQuery,我已经在应用程序的一小部分中使用了它——在单击表格行时突出显示它。为此,我将JQuery 3.0.0的缩小版本与代码捆绑在一起。
- 我使用了IIFE(立即调用的函数表达式),所以你会发现我的整个JavaScript代码被用作(function() { /* My code here */ } ())。
- 要启动应用程序,只需在浏览器中打开文件 sineSum.html。
5. 兴趣点
虽然我已经断断续续地编程了近三十年,但我对HTML5还是比较陌生的。因此,很可能有些地方的代码不是最佳的。我恳请您指出代码中的任何此类缺陷,以便我可以丰富自己,并为后续版本改进代码。
有一件事是肯定的——我非常喜欢开发这个应用程序的狂喜和痛苦。学习用JavaScript编程很有趣。我希望您也会喜欢玩这个应用程序。如果你看到图表在你移动滑块时跳舞感到高兴,请告诉我。如果你觉得事情需要改进,请不要犹豫告诉我。
我使用Visual Studio Code来开发这个应用程序。真的很喜欢使用它——Microsoft的优秀工具。
6. 浏览器兼容性
我已经在我的Windows 51机器上的Chrome(版本0.2704.103.47 m)和Firefox(版本0.7)上对此进行了测试。在我的Macbook Pro上的Safari 8.0.8上,这三者都可以正常工作。
7. 验证
我已经通过为两个程序(Matlab程序和这个JavaScript应用程序)提供几乎相同的振幅和相位值来进行测试。两个程序生成的图表是相似的。
还有一点需要验证。如果两个或多个谐波相位为零,并且叠加,则曲线必须通过点(0,0),(1,0),(2,0),其中0是0 s,1 s和2 s时间时刻的结果和。这也在这个JavaScript应用程序中得到了验证。如果你发现有什么不对劲的地方,请给我回信。
我已经注意确保用户的操作非常有限。这是防止软件出错的一种方法。
8. 总结
在本文中,介绍了一个可视化正弦总和的简单应用程序。这是我的第一个HTML5应用程序,它使我能够真正学习三个部分——HTML,CSS,JavaScript,并带有一点JQuery。此应用程序旨在帮助学生学习正弦和的各个方面。如果至少在某个地方有一个学生实现了这个意图,我会感到很荣幸。
该代码也可在https://github.com/amarnaths0005/SineSum2 中找到。
https://www.codeproject.com/Articles/1109772/SineSum-Sum-of-Sines-in-HTML