Evanyou Blog 彩带
扩大
缩小

当c++遇上音乐

运用到的函数

#include <windows.h>

Beep( f, t );
Sleep( t );

eep() 函数可以让蜂鸣器发出频率为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;

为了偷懒方便,这当中我统一把降音变成了升音……比如降 $B$ 我就用升 $A$ 代替。)

接下来考虑如何计算 t。在编程中,我们可以设置一个常量 T 表示单拍子的时长的一半(因为 Beep 函数中调用的 t 就是时长的一半)。这样,如果一个音符占半拍,那么它的时长 t=T2;如果一个音符占两拍,那么它的时长 t=2T;如果一个休止符占一拍,那么它的时长 t=2T(请特别注意 Sleep 函数与 Beep 函数中 \t\ 的区别)。另外,在乐曲结尾经常有无限延长记号。无限延长记号一般是延长到 6 到 8 拍,最好不要超过 10 拍。

那么如何计算这个常量 T 呢?在一般谱子的左上角,都会有 ♩ = 76、♩ = 84 之类的符号,这意味着该曲以四分音符为一拍,每分钟 76 / 84 拍(取决于等号后面的数字)。

接下来就是小学数学题了。以 ♩ = 76 为例。每分钟 60000 毫秒,每分钟 76 拍,那么每拍占 6000076 毫秒,可以近似取到 800。又因为 T 是时长的一半,所以 T 就应该取 8002,也就是 400。

知道了这些以后,我们看一个例子(小星星):为了偷懒方便,这当中我统一把降音变成了升音……比如降 B 我就用升 A 代替。)

接下来考虑如何计算 t。在编程中,我们可以设置一个常量 T 表示单拍子的时长的一半(因为 Beep 函数中调用的 t 就是时长的一半)。这样,如果一个音符占半拍,那么它的时长 t=T2;如果一个音符占两拍,那么它的时长 t=2T;如果一个休止符占一拍,那么它的时长 t=2T(请特别注意 Sleep 函数与 Beep 函数中 t 的区别)。另外,在乐曲结尾经常有无限延长记号。无限延长记号一般是延长到 6 到 8 拍,最好不要超过 10 拍。

那么如何计算这个常量 T 呢?在一般谱子的左上角,都会有 ♩ = 76、♩ = 84 之类的符号,这意味着该曲以四分音符为一拍,每分钟 76 / 84 拍(取决于等号后面的数字)。

接下来就是小学数学题了。以 ♩ = 76 为例。每分钟 60000 毫秒,每分钟 76 拍,那么每拍占 6000076 毫秒,可以近似取到 800。又因为 T 是时长的一半,所以 T 就应该取 8002,也就是 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 函数的时候不需要一直换算。

posted @ 2019-02-14 13:49  yi_heng  阅读(684)  评论(0编辑  收藏  举报