当 C++ 遇上音乐
前几天在洛谷日报征文中看到了这样一篇文章:C++不止能做题。作为原来校管弦乐队的一名成员,而后因为信息完全放弃了管弦乐队,我看完是又激动又怀念。于是我自行去研究了一下:C++ 如何让蜂鸣器叫出乐曲。
由于本人乐理只有五线谱D2-2级,数学成绩中游,信息也只有普及组水平。如果有哪里写错了,望大家指正、轻 D。
首先需要知道两个函数:
#include <windows.h>
Beep( f, t );
Sleep( t );
Beep() 函数可以让蜂鸣器发出频率为 \(f\) 赫兹,音长大约为 \(2t\) 毫秒的音。(注意是 \(2t\))
Sleep() 函数可以当做休止符用。它可以让程序停止运行 \(t\) 毫秒的时间。
如果想知道每个音对应的频率,可以自行百度十二平均律频率表。以下是三个最常用的八度的频率:
// _在前表示低音, 在后表示高音
// o表示升
const int _oC = 277, _oD = 311, _oF = 370, _oG = 415, _oA = 466;
const int _C = 262, _D = 294, _E = 330, _F = 349, _G = 392, _A = 440, _B = 494;
const int oC = 554, oD = 622, oF = 740, oG = 831, oA = 932;
const int C = 523, D = 578, E = 659, F = 698, G = 784, A = 880, B = 988;
const int C_ = 1047, D_ = 1175, E_ = 1319, F_ = 1397, G_ = 1568, A_ = 1760, B_ = 1976;
const int oC_ = 1109, oD_ = 1245, oF_ = 1480, oG_ = 1661, oA_ = 1865;
(为了偷懒方便,这当中我统一把降音变成了升音……比如降 \(\text{B}\) 我就用升 \(\text{A}\) 代替。)
接下来考虑如何计算 \(t\)。在编程中,我们可以设置一个常量 \(T\) 表示单拍子的时长的一半(因为 Beep 函数中调用的 \(t\) 就是时长的一半)。这样,如果一个音符占半拍,那么它的时长 \(t = \frac{T}{2}\);如果一个音符占两拍,那么它的时长 \(t = 2T\);如果一个休止符占一拍,那么它的时长 \(t = 2T\)(请特别注意 Sleep 函数与 Beep 函数中 \(t\) 的区别)。另外,在乐曲结尾经常有无限延长记号。无限延长记号一般是延长到 \(6\) 到 \(8\) 拍,最好不要超过 \(10\) 拍。
那么如何计算这个常量 \(T\) 呢?在一般谱子的左上角,都会有 ♩ = 76、♩ = 84 之类的符号,这意味着该曲以四分音符为一拍,每分钟 76 / 84 拍(取决于等号后面的数字)。
接下来就是小学数学题了。以 ♩ = 76 为例。每分钟 \(60000\) 毫秒,每分钟 \(76\) 拍,那么每拍占 \(\frac{60000}{76}\) 毫秒,可以近似取到 \(800\)。又因为 \(T\) 是时长的一半,所以 \(T\) 就应该取 \(\frac{800}{2}\),也就是 \(400\)。
知道了这些以后,我们看一个例子(小星星):
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <windows.h>
using namespace std;
// _在前表示低音, 在后表示高音
// o表示升
const int _oC = 277, _oD = 311, _oF = 370, _oG = 415, _oA = 466;
const int _C = 262, _D = 294, _E = 330, _F = 349, _G = 392, _A = 440, _B = 494;
const int oC = 554, oD = 622, oF = 740, oG = 831, oA = 932;
const int C = 523, D = 578, E = 659, F = 698, G = 784, A = 880, B = 988;
const int C_ = 1047, D_ = 1175, E_ = 1319, F_ = 1397, G_ = 1568, A_ = 1760, B_ = 1976;
const int oC_ = 1109, oD_ = 1245, oF_ = 1480, oG_ = 1661, oA_ = 1865;
const int T = 400; //一拍的长度
const int Stop = 800; //一拍休止符的长度
int main()
{
Beep( C, T );
Beep( C, T );
Beep( G, T );
Beep( G, T );
Beep( A, T );
Beep( A, T );
Beep( G, T * 2 );
Beep( F, T );
Beep( F, T );
Beep( E, T );
Beep( E, T );
Beep( D, T );
Beep( D, T );
Beep( C, T * 2 );
Beep( G, T );
Beep( G, T );
Beep( F, T );
Beep( F, T );
Beep( E, T );
Beep( E, T );
Beep( D, T * 2 );
Beep( G, T );
Beep( G, T );
Beep( F, T );
Beep( F, T );
Beep( E, T );
Beep( E, T );
Beep( D, T * 2 );
Beep( C, T );
Beep( C, T );
Beep( G, T );
Beep( G, T );
Beep( A, T );
Beep( A, T );
Beep( G, T * 2 );
Beep( F, T );
Beep( F, T );
Beep( E, T );
Beep( E, T );
Beep( D, T );
Beep( D, T );
Beep( C, T * 4 );
return 0;
}
这里面多了一个常量 \(Stop\),用于表示休止符的一拍,这样书写起来可以方便许多,调用 Sleep 函数的时候不需要一直换算。
我还无聊地打了另外几首歌。
《团结就是力量》
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <windows.h>
using namespace std;
// _在前表示低音, 在后表示高音
// o表示升
const int _oC = 277, _oD = 311, _oF = 370, _oG = 415, _oA = 466;
const int _C = 262, _D = 294, _E = 330, _F = 349, _G = 392, _A = 440, _B = 494;
const int oC = 554, oD = 622, oF = 740, oG = 831, oA = 932;
const int C = 523, D = 578, E = 659, F = 698, G = 784, A = 880, B = 988;
const int C_ = 1047, D_ = 1175, E_ = 1319, F_ = 1397, G_ = 1568, A_ = 1760, B_ = 1976;
const int oC_ = 1109, oD_ = 1245, oF_ = 1480, oG_ = 1661, oA_ = 1865;
const int T = 400;
const int Stop = 800;
int main()
{
Beep( C_, T * 2 );
Beep( G, T );
Beep( E, T / 4 * 3 );
Beep( D, T / 4 );
Beep( C, T );
Beep( G, T );
Beep( E, T );
Sleep( Stop );
Beep( C_, T * 2 );
Beep( G, T );
Beep( E, T / 4 * 3 );
Beep( D, T / 4 );
Beep( C, T );
Beep( A, T );
Beep( G, T );
Sleep( Stop / 2 );
Beep( G, T / 2 );
Beep( C_, T );
Beep( A, T / 2 );
Beep( G, T / 2 );
Beep( C_, T );
Sleep( Stop / 2 );
Beep( G, T / 2 );
Beep( C_, T );
Beep( A, T / 2 );
Beep( G, T / 2 );
Beep( A, T );
Sleep( Stop / 2 );
Beep( E, T / 2 );
Beep( C_, T / 2 * 3 );
Beep( A, T / 2 );
Beep( G, T );
Beep( E, T );
Beep( C_, T / 2 * 3 );
Beep( A, T / 2 );
Beep( C_, T );
Sleep( Stop );
Beep( C_, T );
Beep( G, T );
Beep( E, T / 2 );
Beep( A, T / 2 );
Beep( G, T / 2 );
Beep( E, T / 2 );
Beep( D, T / 2 * 3 );
Beep( C, T / 2 );
Beep( E, T );
Sleep( Stop / 2 );
Beep( G, T / 2 );
Beep( C_, T );
Beep( G, T );
Beep( A, T / 2 );
Beep( C_, T / 2 );
Beep( A, T / 2 );
Beep( G, T / 2 );
Beep( E, T );
Beep( E, T / 2 );
Beep( C, T / 2 );
Beep( A, T * 2 );
Beep( A, T );
Sleep( Stop );
Beep( C_, T / 4 * 3 );
Beep( C_, T / 4 );
Beep( G, T / 2 );
Beep( G, T / 2 );
Beep( D, T / 4 * 3 );
Beep( E, T / 4 );
Beep( G, T / 2 );
Beep( G, T / 2 );
Beep( A, T / 2 * 3 );
Beep( G, T / 2 );
Beep( A, T );
Beep( D_, T );
Beep( C_, T );
Beep( A, T / 2 );
Beep( G, T / 2 );
Beep( C_, T );
Beep( A, T / 2 );
Beep( G, T / 2 );
Beep( E, T * 2 );
Beep( C_, T );
Sleep( Stop );
return 0;
}
可以明显听出,当节奏快起来的时候,蜂鸣器发音的速度就有点赶不上了。所以这种方法局限性还是很强的,只适合打小夜曲之类的……
最后附上我们学校的校歌(原曲是 G 大调的,但是我太弱了不知道怎么弄……于是降成 C 大调写了)。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <windows.h>
using namespace std;
// _在前表示低音, 在后表示高音
// o表示升
const int _oC = 277, _oD = 311, _oF = 370, _oG = 415, _oA = 466;
const int _C = 262, _D = 294, _E = 330, _F = 349, _G = 392, _A = 440, _B = 494;
const int oC = 554, oD = 622, oF = 740, oG = 831, oA = 932;
const int C = 523, D = 578, E = 659, F = 698, G = 784, A = 880, B = 988;
const int C_ = 1047, D_ = 1175, E_ = 1319, F_ = 1397, G_ = 1568, A_ = 1760, B_ = 1976;
const int oC_ = 1109, oD_ = 1245, oF_ = 1480, oG_ = 1661, oA_ = 1865;
const int T = 400;
const int Stop = 800;
int main()
{
Beep( C, T );
Beep( A, T * 2 );
Beep( A, T );
Beep( F, T );
Beep( C, T );
Beep( C, T );
Beep( F, T * 2 );
Beep( E, T );
Beep( D, T * 3 );
Beep( _B, T / 2 );
Beep( _B, T / 2 );
Beep( _A, T );
Beep( E, T );
Beep( D, T * 2 );
Beep( _A, T );
Beep( _B, T );
Beep( C, T * 3 );
Beep( _E, T );
Beep( _A, T / 2 );
Beep( _B, T / 2 );
Beep( C, T / 2 );
Beep( D, T / 2 );
for ( int i = 1; i <= 2; ++i ) {
Beep( E, T );
Beep( E, T );
Beep( E, T );
Beep( D, T / 2 * 3 );
Beep( E, T / 2 );
Beep( C, T );
Beep( _B, T * 2 );
Beep( _A, T / 2 );
Beep( _G, T / 2 );
Beep( _A, T * 5 );
Beep( _A, T );
Beep( _G, T );
Beep( C, T );
Beep( E, T );
Beep( G, T * 2 );
Beep( E, T );
Beep( F, T / 2 * 3 );
Beep( E, T / 2 );
Beep( D, T / 2 );
Beep( _A, T / 2 );
Beep( D, T * 6 );
Beep( E, T );
Beep( E, T );
Beep( E, T );
Beep( D, T / 2 * 3 );
Beep( E, T / 2 );
Beep( C, T );
Beep( _B, T );
Beep( _B, T / 2 );
Beep( _B, T / 2 );
Beep( _A, T / 2 );
Beep( _G, T / 2 );
Beep( _A, T * 2 );
Beep( _A, T );
Beep( _G, T );
Beep( C, T );
Beep( E, T );
Beep( G, T * 3 );
Beep( F, T * 2 );
Beep( F, T );
Beep( E, T / 2 * 3 );
Beep( E, T / 2 );
Beep( D, T / 4 * 3 );
Beep( E, T / 4 );
Beep( C, T * 5 );
Beep( C, T / 2 );
Beep( C, T / 2 );
Beep( A, T );
Beep( A, T );
Beep( A, T );
Beep( G, T );
Beep( F, T );
Beep( E, T );
Beep( D, T * 2 );
Beep( C, T );
Beep( G, T * 3 );
Beep( F, T / 2 );
Beep( E, T / 2 );
Beep( D, T );
Beep( _A, T / 2 );
Beep( _B, T / 2 * 3 );
Beep( _A, T / 2 );
Beep( _B, T / 2 );
Beep( C, T / 2 );
Beep( D, T * 5 );
Beep( C, T / 2 );
Beep( C, T / 2 );
Beep( A, T );
Beep( A, T );
Beep( A, T );
Beep( G, T );
Beep( F, T );
Beep( E, T );
Beep( D, T * 2 );
Beep( E, T );
Beep( _A, T * 3 );
Beep( _B, T / 2 );
Beep( _B, T / 2 );
Beep( _A, T );
Beep( E, T );
Beep( D, T / 2 * 3 );
Sleep( Stop / 2 );
Beep( _A, T / 2 );
Beep( _B, T / 2 );
Beep( C, T * 6 );
}
Beep( G, T * 3 );
Beep( G, T * 3 );
Beep( C_, T * 10 );
Sleep( Stop * 2 );
return 0;
}
当 C++ 遇上音乐的更多相关文章
- 当c++遇上音乐
运用到的函数 #include <windows.h> Beep( f, t ); Sleep( t ); eep() 函数可以让蜂鸣器发出频率为f赫兹,音长大约为 2t 毫秒的音.(注意 ...
- MVC遇上bootstrap后的ajax表单模型验证
MVC遇上bootstrap后的ajax表单验证 使用bootstrap后他由他自带的样式has-error,想要使用它就会比较麻烦,往常使用jqueyr.validate的话只有使用他自己的样式了, ...
- 敏捷遇上UML-需求分析及软件设计最佳实践(郑州站 2014-6-7)
邀请函: 尊敬的阁下:我们将在郑州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实 ...
- 敏捷遇上UML—软创基地马年大会(广州站 2014-4-19)
我们将在广州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战技巧. 时间:2 ...
- 敏捷遇上UML——软创基地马年大会(深圳站 2014-3-15)
邀请函: 尊敬的阁下: 我们将在深圳为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战 ...
- 初识genymotion安装遇上的VirtualBox问题
想必做过Android开发的都讨厌那慢如蜗牛的 eclipse原生Android模拟器吧! 光是启动这个模拟器都得花上两三分钟,慢慢的用起来手机来调试,但那毕竟不是长久之计,也确实不方便,后来知道了g ...
- SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败解决方案
SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败的问题,可作如下尝试: 更新失败后,在windows的[事件查看器→应用程序]中找到来源为MsiInstaller,事件ID为1 ...
- 当创业遇上O2O,新一批死亡名单,看完震惊了!
当创业遇上O2O,故事就开始了,总投入1.6亿.半年开7家便利店.会员猛增至10万……2015半年过去后,很多故事在后面变成了一场创业“事故”,是模式错误还是烧钱过度?这些项目的失败能给国内创业者带来 ...
- LoadRunner - 当DiscuzNT遇上了Loadrunner(下) (转发)
当DiscuzNT遇上了Loadrunner(下) 在之前的两篇文章中,基本上介绍了如何录制脚本和生成并发用户,同时还对测试报告中的几个图表做了简单的说明.今天这篇文章做为这个系列的最后一篇,将会介绍 ...
随机推荐
- 在VM虚拟机中安装Centos操作系统
首先我们要下载 Centos https://www.centos.org/ 这个是Centos官方 最新版本 7 https://www.centos.org/download/ 提供有 DVD安 ...
- matlab2014a 转化c语言
一.原因错误 第一种,命令窗口测试代码mbulid -setup 出错 , 就是电脑没有安装sdk7.1 网上有很多安装教程(注意要有vc++2010要卸载,具体看网上教程,安装好了要更性vc++ ...
- 【QT】qt python install pip
https://pip.pypa.io/en/stable/installing/ http://www.runoob.com/w3cnote/python-pip-install-usage.htm ...
- 多个页面引用公共的头部 header.html 和尾部 footer.html
方法:通过load()函数,引入公共头部和尾部文件; js代码预览: $(".headerPage").load("header.html"); $(" ...
- sping_依赖注入的三种方式
1. set注入:通过setxxx()给属性赋值 <!--id是对象--> <!--class是类--> <bean id = "student" ...
- 2019微信浏览器跳转外部浏览器下载app打开任意站实现方法
很多朋友问我怎么解决微信内点击链接或扫描二维码可以直接跳出微信在外部浏览器打开网页链接和下载APP,其实这并不难,只要我们实现微信跳转功能即可.下面给大家介绍这个功能 方案实现教程: 功能目的 生成微 ...
- PHP fwrite 函数:将字符串写入文件(追加与换行)
PHP fwrite() fwrite() 函数用于向文件写入字符串,成功返回写入的字符数,否则返回 FALSE . 语法: int fwrite( resource handle, string s ...
- Lintcode: Knight Shortest Path
Given a knight in a chessboard (a binary matrix with 0 as empty and 1 as barrier) with a source posi ...
- EL有11个隐含对象
EL有11个隐含对象: 隐含对象 类型 说明 ...
- Java获取项目根目录等其他系统属性
一 相对路径的获得 说明:相对路径(即不写明时候到底相对谁)均可通过以下方式获得(不论是一般的java项目还是web项目) String relativelyPath=System.getProper ...