C语言——音乐演奏

        事情的起因是在某站看到有好多UP拿C++和C实现了通过一个函数打谱演奏音乐,所以就想自己尝试一下,本文为感兴趣的朋友分享一点个人的经验。

        

1.Beep函数

头文件

#include<windows.h>

用法

Beep(100,100) //参数:发音频率 持续时间

 音阶参数

//低音区
#define L_DO 262
#define L_RE 294 
#define L_M  330
#define L_FA 349
#define L_SO 392
#define L_LA 440
#define L_SI 494

//中音区
#define DO  523
#define RE  587
#define M   659
#define FA  698
#define SO  784
#define LA  880
#define SI  988

//高音区
#define H_DO  1046
#define H_RE  1175
#define H_M   1318
#define H_FA  1397
#define H_SO  1568
#define H_LA  1760
#define H_SI  1976

//节拍
#define Q  882   //四分音符
#define E  Q/2  //八分音符

        这些频率是对照音阶表定义的,持续时间这里是2/4节拍和68的速度来举例的,使用宏定义可以方便修改 。

        最开始是想使用Beep函数进行蜂鸣器发声,但是这个声音并不是很理想,而且停顿的感觉也很明显,所以采用了更加强力的一个函数。

2.midi函数

头文件

#include<windows.h>
#include <stdio.h>
#include<iostream>
#include<mmsystem.h>
#include<mutex>
#pragma comment (lib,"winmm.lib")
using namespace std;

用法

1、HMIDIOUT函数
HMIDIOUT 是Windows多媒体编程中用于表示 MIDI 输出设备句柄的一个类型。在Windows的MIDI(Musical Instrument Digital Interface,乐器数字接口)编程接口中,当你成功打开一个MIDI输出设备时,系统会返回一个 HMIDIOUT 类型的句柄,你可以通过这个句柄向MIDI设备发送各种MIDI消息,如音符、控制信息等。

简单来说,就是将你电脑上的midi音乐播放设备起一个名字,方便以后调用

例如:

HMIDIOUT handle;


这里就定义了一个名为handle的句柄用于以后的midi函数传参

2、midiOutOpen函数
midiOutOpen 是Windows多媒体API中用于打开MIDI输出设备的一个函数。在Windows编程中,如果你需要与MIDI输出设备(如声卡上的MIDI端口或外部MIDI合成器)交互并发送MIDI消息,通常会使用这个函数来获取到该设备的句柄。

参数如下

MMRESULT midiOutOpen(
    LPHMIDIOUT lphMidiOut,
    UINT uDeviceID,
    DWORD_PTR dwCallback,
    DWORD_PTR dwInstance,
    DWORD fdwOpen
);


参数说明:

LPHMIDIOUT lphMidiOut:指向一个 HMIDIOUT 类型的变量的指针,函数成功执行后,将在此处存储打开的MIDI输出设备的句柄。这里要输入的值也就是上面HMIDIOUT函数定义的句柄,通俗的说,就是你给midi设备起的名字。

UINT uDeviceID:指定要打开的MIDI输出设备的标识符。开发者可以通过调用 midiOutGetNumDevs 函数获取系统中 MIDI 输出设备的总数,然后使用 midiOutGetDevCaps 函数获取每个设备的具体信息,包括设备的 uDeviceID。在实际应用中,开发者根据需求选择合适的 uDeviceID 来打开或操作对应的 MIDI 输出设备。

DWORD_PTR dwCallback:如果希望使用回调函数来处理MIDI输出消息,可以提供一个回调函数的地址。若不需要回调,则设置为NULL。

DWORD_PTR dwInstance:应用程序定义的数据,当调用回调函数时作为参数传递。如果不需要回调函数,则此参数无效。

DWORD fdwOpen:在 midiOutOpen 函数中,fdwOpen 参数用于指定打开 MIDI 输出设备时的一些附加选项或行为特征。它可以是一个或多个预定义的标志组合(通过按位或运算符 | 组合)。例如:

CALLBACK_NULL:表示不使用回调函数。
CALLBACK_WINDOW 或 CALLBACK_TASK:表明使用窗口消息或线程回调函数来通知 MIDI 消息的发送完成情况。
CALLBACK_FUNCTION:使用函数指针作为回调函数。
MIDI_IO_STATUS:在回调函数中包含 MIDI 输入/输出的状态信息。
函数成功执行后返回值是 MMSYSERR_NOERROR,表示成功打开了指定的MIDI输出设备;否则返回相应的错误代码。

在这里,我们并不需要使用回调函数,所以,我们只需要写成如下格式即可:

midiOutOpen(&handle, 0, 0, 0, CALLBACK_NULL);


 3、midiOutShortMsg函数
 midiOutShortMsg 是 Windows 多媒体(Multimedia)API 提供的一个函数,用于直接发送短 MIDI 消息到已打开的 MIDI 输出设备。这个函数适用于发送单个 MIDI 消息,消息长度不超过三个字节(因为标准 MIDI 消息最多包含三部分:status byte、data1 和 data2)。

函数原型如下:

​MMRESULT midiOutShortMsg(
    HMIDIOUT hmo, 
    DWORD dwMsg
);


参数说明:

HMIDIOUT hmo:这是通过 midiOutOpen 函数打开 MIDI 输出设备时返回的设备句柄。

DWORD dwMsg:这是一个包含整个 MIDI 消息的 DWORD 值。其中,低字节包含 MIDI 消息的状态字节,接下来的两个字节分别包含 MIDI 数据1和数据2。如果 MIDI 消息只需要一个或两个数据字节,那么高位字节应当填充为0。

第一个参数就是我们midi音乐设备的名字

第二个参数则要参照midi通信协议了

这里用通俗的语言讲一下:

(1)音符弹奏
假如我们想让midi设备在第一声道(0—f)上以100(0—127)的声音大小弹奏中央C(音码为60)则代码如下:

midiOutShortMsg(handle, 0x00643C90);


其中0x00并无意义,但要加上0x前缀在0x之后有多少0也对消息没有影响,

64为100的16进制数,代表音量大小;

3c为60的16进制数,代表音调;

90为第一声道,具体声道值为90—9f,其中99声道为类似鼓声的音色,而a—f声道发音较为短促,我们这里依照情况使用9声道及其后的声道。

也就是说,我们需要按顺序填写4个部分,即:0x00前缀、音量、音调、声道。

这样就能按照我们所想弹奏出需要的音符了

(2)音色切换
我们还可以使用此函数切换音色,

代码如下:

midiOutShortMsg(handle, 0xC000); //设置通道0的乐器为 大钢琴
在这里除了0x前缀外有两个参数

c0表示改变声道0的音色,我们也可以举一反三,设置为c1、c2等,c后面跟随的数字表示为声道数

00则是乐器的代表数字,00代表大钢琴

也就是说,这个命令将声道0的乐器设置为大钢琴

我将具体状态参数与音色表、音码表放在附录里供大家参考,如有其他需要请自行查阅。

4、midiOutClose函数
midiOutClose 是Windows多媒体(Multimedia)API中用于关闭已打开的MIDI输出设备的函数。当你不再需要向某个MIDI输出设备发送消息,或者应用程序即将退出时,应调用此函数来释放系统资源。

函数原型如下:

MMRESULT midiOutClose(HMIDIOUT hmo);
参数说明:

HMIDIOUT hmo:这是通过 midiOutOpen 函数成功打开 MIDI 输出设备时返回的设备句柄。
也就是说演奏完成后需要将我们的midi设备关闭,与midiOutOpen函数不同的是:我们只需要输入要关闭的设备名称即可 

代码如下:

midiOutClose(handle);

这部分函数来自csdn一位博主,代码实现思路也是参考了这篇文章。
                        
原文链接:https://blog.csdn.net/Zjs15630471263/article/details/137217417

音阶参数

enum Scale  //音阶参数
{
    Rest = 0, C8 = 108, B7 = 107, A7s = 106, A7 = 105, G7s = 104, G7 = 103, F7s = 102, F7 = 101, E7 = 100,
    D7s = 99, D7 = 98, C7s = 97, C7 = 96, B6 = 95, A6s = 94, A6 = 93, G6s = 92, G6 = 91, F6s = 90, F6 = 89,
    E6 = 88, D6s = 87, D6 = 86, C6s = 85, C6 = 84, B5 = 83, A5s = 82, A5 = 81, G5s = 80, G5 = 79, F5s = 78,
    F5 = 77, E5 = 76, D5s = 75, D5 = 74, C5s = 73, C5 = 72, B4 = 71, A4s = 70, A4 = 69, G4s = 68, G4 = 67,
    F4s = 66, F4 = 65, E4 = 64, D4s = 63, D4 = 62, C4s = 61, C4 = 60, B3 = 59, A3s = 58, A3 = 57, G3s = 56,
    G3 = 55, F3s = 54, F3 = 53, E3 = 52, D3s = 51, D3 = 50, C3s = 49, C3 = 48, B2 = 47, A2s = 46, A2 = 45,
    G2s = 44, G2 = 43, F2s = 42, F2 = 41, E2 = 40, D2s = 39, D2 = 38, C2s = 37, C2 = 36, B1 = 35, A1s = 34,
    A1 = 33, G1s = 32, G1 = 31, F1s = 30, F1 = 29, E1 = 28, D1s = 27, D1 = 26, C1s = 25, C1 = 24, B0 = 23,
    A0s = 22, A0 = 21
};

 3.歌词与曲谱

char ci[62][40] = {
"光 是谁燃烛照亮\n",
"时间设下的迷藏\n",
"光 置换明暗立场 肆意流淌\n",
"看 谁站过的地方\n",
"棋局已百孔千疮\n",
"看 眼前最真假相 假又何妨\n",
"怀揣着炽烈顽心走向\n",
"最宽容刑场\n",
"裂过碎过 都空洞地回响\n",
"到最后竟庆幸于夕阳\n",
"仍留在身上\n",
"来不及讲 故事多跌宕\n",
"有最崎崛的峰峦\n",
"成全过你我张狂\n",
"海上清辉与圆月 盛进杯光\n",
"有最孤傲的雪山\n",
"静听过你我诵章\n",
"世人惊羡的桥段 不过寻常\n",

"光 可寻来路艰险\n",
"也可照前路坦荡\n",
"光 补填残陋世相 无须度量\n",
"看 你计算的无常\n",
"和你来时的彷徨\n",
"看 终有勇气独挡 人世荒唐\n",
"怀揣着炽烈顽心走向\n",
"最宽容刑场\n",
"裂过碎过 都空洞地回响\n",
"到最后竟庆幸于夕阳\n",
"仍留在身上\n",
"来不及讲 故事多跌宕\n",
"有最崎崛的峰峦\n",
"成全过你我张狂\n",
"海上清辉与圆月 盛进杯光\n",
"有最孤傲的雪山\n",
"静听过你我诵章\n",
"世人惊羡的桥段 不过寻常\n",

"有最崎崛的峰峦\n",
"成全过你我张狂\n",
"海上清辉与圆月 盛进杯光\n",
"有最残破的书简\n",
"记载过光阴漫长\n",

"无意拾过的片瓦 历数寒凉\n",
"有最孤傲的雪山\n",
"静听过你我诵章\n",
"世人惊羡的桥段 不过寻常\n",
"有最清瘦的字迹\n",
"都已随记忆泛黄\n",
"而我再度铺垫起 下个篇章\n"};

int qu[]{

        9,A4,_,_,_,G4,_,A4,_,B4,_,C5,B4,_,G4,_,_,9,//光 是谁燃烛照亮
        A4,_,_,_,G4,_,A4,_,B4,_,C5,B4,_,F3,_,9,//时间设下的迷藏
        A4,_,_,_,G3,_,A4,_,B4,_,C5,B4,_,_,G4,_,_,_,Rest,A4,_,G4,E4,_,G4,_,_,9,//光 置换明暗立场 肆意流淌
        A4,_,_,_,G4,_,A4,_,B4,_,C5,B4,_,G4,_,_,9,//看 谁站过的地方
        A4,_,_,_,G4,_,A4,_,B4,_,C5,D5,_,C5,_,_,9,//棋局已百孔千疮
        A4,_,_,_,G4,_,A4,_,B4,_,C5,D5,_,B4,_,_,C5,_,_,Rest,B4,C5,_,_,_,9, //看眼前最真假相 假 又何妨
        C5,D5,E5,_,_,_,G5,_,G5,_,E5,D5,_,C5,_,_,9,//怀揣着炽烈顽心走向
        A4,_,E5,D5,_,C5,_,A4,_,_,_,9,//最宽容刑场
        Rest,G4,A4,_,E5,D5,_,E5,_,_,G5,_,E5,D5,_,C5,_,_,_,E5,_,_,Rest,_,9,//裂过碎过
        Rest,C5,D5,E5,_,_,E5,_,_,_,G5,_,G5,_,E5,D5,_,D5,_,_,9,//到最后
        A5,_,E5,D5,_,G5,_,_,C5,_,_,_,9,//仍留在身上
        Rest,_,G4,A4,_,E5,D5,_,E5,_,_,G5,_,_,A5,_,E5,_,G5,_,_,Rest,_,_,_,9,//来不及讲

        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,//有最奇绝的峰峦
        A5,_,G5,_,E5,_,G5,D5,_,G5,_,_,C5,_,_,_,9,//
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,D6,_,_,E6,G6,_,E6,_,E6,_,_,Rest,_,_,9,//海上清辉与圆月
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,//
        A5,_,G5,_,E5,_,G5,A5,_,B5,_,_,A5,_,_,_,9,//
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,B5,_,_,B5,C6,_,B5,_,_,_,A5,_,_,_,_,_,_,9,//世人惊羡的桥段不过寻常

        Rest,Rest,Rest,

        A4,_,_,_,G4,_,A4,_,B4,_,C5,B4,_,G4,_,_,9,//光 是谁燃烛照亮
        A4,_,_,_,G4,_,A4,_,B4,_,C5,B4,_,F3,_,9,//时间设下的迷藏
        A4,_,_,_,G3,_,A4,_,B4,_,C5,B4,_,_,G4,_,_,_,Rest,A4,_,G4,E4,_,G4,_,_,9,//光 置换明暗立场 肆意流淌
        A4,_,_,_,G4,_,A4,_,B4,_,C5,B4,_,G4,_,_,9,//看 谁站过的地方
        A4,_,_,_,G4,_,A4,_,B4,_,C5,D5,_,C5,_,_,9,//棋局已百孔千疮
        A4,_,_,_,G4,_,A4,_,B4,_,C5,D5,_,B4,_,_,C5,_,_,Rest,B4,C5,_,_,_,9, //看眼前最真假相 假 又何妨
        C5,D5,E5,_,_,_,G5,_,G5,_,E5,D5,_,C5,_,_,9,//怀揣着炽烈顽心走向
        A4,_,E5,D5,_,C5,_,A4,_,_,_,9,//最宽容刑场
        Rest,G4,A4,_,E5,D5,_,E5,_,_,G5,_,E5,D5,_,C5,_,_,_,E5,_,_,Rest,_,9,//裂过碎过
        Rest,C5,D5,E5,_,_,E5,_,_,_,G5,_,G5,_,E5,D5,_,D5,_,_,9,//到最后
        A5,_,E5,D5,_,G5,_,_,C5,_,_,_,9,//仍留在身上
        Rest,_,G4,A4,_,E5,D5,_,E5,_,_,G5,_,_,A5,_,E5,_,G5,_,_,Rest,_,_,_,9,//来不及讲

        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,//有最奇绝的峰峦
        A5,_,G5,_,E5,_,G5,D5,_,G5,_,_,C5,_,_,_,9,//
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,D6,_,_,E6,G6,_,E6,_,E6,_,_,Rest,_,_,9,//海上清辉与圆月
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,//
        A5,_,G5,_,E5,_,G5,A5,_,B5,_,_,A5,_,_,_,9,//
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,B5,_,_,B5,C6,_,B5,_,_,_,A5,_,_,_,_,_,_,9,//世人惊羡的桥段不过寻常

        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,//有最奇绝的峰峦
        A5,_,G5,_,E5,_,G5,D5,_,G5,_,_,C5,_,_,_,9,//
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,D6,_,_,E6,G6,_,E6,_,E6,_,_,Rest,_,_,9,//海上清辉与圆月
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,//
        A5,_,G5,_,E5,_,G5,A5,_,B5,_,_,A5,_,_,_,9,//

        E5,_,G5,_,B5,_,B5,C6,_,B5,_,_,A5,_,_,9,//
        A5,_,G5,_,E5,_,G5,D5,_,G5,_,_,C5,_,_,_,9,//
        Rest,E5,G5,B5,_,_,E5,C6,_,B5,_,_,_,A5,_,_,9,
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,D6,_,_,E6,G6,_,E6,_,E6,_,_,Rest,_,_,9,
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,
        A5,_,G5,_,E5,_,G5,A5,_,B5,_,_,A5,_,_,_,9,
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,B5,C6,_,B5,_,_,_,_,A5,_,_,_,-999
  };

        歌词按照你要谱的曲子一行一行复制就OK,对于怎么写这个程序写的谱子,首先看这首曲的节奏,像十年人间这首歌是2/4的节奏,然后,曲子中最小的节拍是十六分之一拍。所以就可以这样去写:            

           A4,_,_,_,        G4,_,       A4,_,             B4,_,         C5          ,B4,         _,     G4,_,_

        四分音符就让一个音符持续4倍的时间,同理,延音符,也多持续一倍的时间(实际应该只持续一半的时间)。

4.》《盗墓笔记 十年人间》播放代码

#include<windows.h>
#include <stdio.h>
#include<iostream>
#include<mmsystem.h>
#include<mutex>
#pragma comment (lib,"winmm.lib")
using namespace std;


enum Scale  //音阶参数
{
    Rest = 0, C8 = 108, B7 = 107, A7s = 106, A7 = 105, G7s = 104, G7 = 103, F7s = 102, F7 = 101, E7 = 100,
    D7s = 99, D7 = 98, C7s = 97, C7 = 96, B6 = 95, A6s = 94, A6 = 93, G6s = 92, G6 = 91, F6s = 90, F6 = 89,
    E6 = 88, D6s = 87, D6 = 86, C6s = 85, C6 = 84, B5 = 83, A5s = 82, A5 = 81, G5s = 80, G5 = 79, F5s = 78,
    F5 = 77, E5 = 76, D5s = 75, D5 = 74, C5s = 73, C5 = 72, B4 = 71, A4s = 70, A4 = 69, G4s = 68, G4 = 67,
    F4s = 66, F4 = 65, E4 = 64, D4s = 63, D4 = 62, C4s = 61, C4 = 60, B3 = 59, A3s = 58, A3 = 57, G3s = 56,
    G3 = 55, F3s = 54, F3 = 53, E3 = 52, D3s = 51, D3 = 50, C3s = 49, C3 = 48, B2 = 47, A2s = 46, A2 = 45,
    G2s = 44, G2 = 43, F2s = 42, F2 = 41, E2 = 40, D2s = 39, D2 = 38, C2s = 37, C2 = 36, B1 = 35, A1s = 34,
    A1 = 33, G1s = 32, G1 = 31, F1s = 30, F1 = 29, E1 = 28, D1s = 27, D1 = 26, C1s = 25, C1 = 24, B0 = 23,
    A0s = 22, A0 = 21
};

char ci[62][40] = {
"光 是谁燃烛照亮\n",
"时间设下的迷藏\n",
"光 置换明暗立场 肆意流淌\n",
"看 谁站过的地方\n",
"棋局已百孔千疮\n",
"看 眼前最真假相 假又何妨\n",
"怀揣着炽烈顽心走向\n",
"最宽容刑场\n",
"裂过碎过 都空洞地回响\n",
"到最后竟庆幸于夕阳\n",
"仍留在身上\n",
"来不及讲 故事多跌宕\n",
"有最崎崛的峰峦\n",
"成全过你我张狂\n",
"海上清辉与圆月 盛进杯光\n",
"有最孤傲的雪山\n",
"静听过你我诵章\n",
"世人惊羡的桥段 不过寻常\n",

"光 可寻来路艰险\n",
"也可照前路坦荡\n",
"光 补填残陋世相 无须度量\n",
"看 你计算的无常\n",
"和你来时的彷徨\n",
"看 终有勇气独挡 人世荒唐\n",
"怀揣着炽烈顽心走向\n",
"最宽容刑场\n",
"裂过碎过 都空洞地回响\n",
"到最后竟庆幸于夕阳\n",
"仍留在身上\n",
"来不及讲 故事多跌宕\n",
"有最崎崛的峰峦\n",
"成全过你我张狂\n",
"海上清辉与圆月 盛进杯光\n",
"有最孤傲的雪山\n",
"静听过你我诵章\n",
"世人惊羡的桥段 不过寻常\n",

"有最崎崛的峰峦\n",
"成全过你我张狂\n",
"海上清辉与圆月 盛进杯光\n",
"有最残破的书简\n",
"记载过光阴漫长\n",

"无意拾过的片瓦 历数寒凉\n",
"有最孤傲的雪山\n",
"静听过你我诵章\n",
"世人惊羡的桥段 不过寻常\n",
"有最清瘦的字迹\n",
"都已随记忆泛黄\n",
"而我再度铺垫起 下个篇章\n"};

int qu[]{

        9,A4,_,_,_,G4,_,A4,_,B4,_,C5,B4,_,G4,_,_,9,//光 是谁燃烛照亮
        A4,_,_,_,G4,_,A4,_,B4,_,C5,B4,_,F3,_,9,//时间设下的迷藏
        A4,_,_,_,G3,_,A4,_,B4,_,C5,B4,_,_,G4,_,_,_,Rest,A4,_,G4,E4,_,G4,_,_,9,//光 置换明暗立场 肆意流淌
        A4,_,_,_,G4,_,A4,_,B4,_,C5,B4,_,G4,_,_,9,//看 谁站过的地方
        A4,_,_,_,G4,_,A4,_,B4,_,C5,D5,_,C5,_,_,9,//棋局已百孔千疮
        A4,_,_,_,G4,_,A4,_,B4,_,C5,D5,_,B4,_,_,C5,_,_,Rest,B4,C5,_,_,_,9, //看眼前最真假相 假 又何妨
        C5,D5,E5,_,_,_,G5,_,G5,_,E5,D5,_,C5,_,_,9,//怀揣着炽烈顽心走向
        A4,_,E5,D5,_,C5,_,A4,_,_,_,9,//最宽容刑场
        Rest,G4,A4,_,E5,D5,_,E5,_,_,G5,_,E5,D5,_,C5,_,_,_,E5,_,_,Rest,_,9,//裂过碎过
        Rest,C5,D5,E5,_,_,E5,_,_,_,G5,_,G5,_,E5,D5,_,D5,_,_,9,//到最后
        A5,_,E5,D5,_,G5,_,_,C5,_,_,_,9,//仍留在身上
        Rest,_,G4,A4,_,E5,D5,_,E5,_,_,G5,_,_,A5,_,E5,_,G5,_,_,Rest,_,_,_,9,//来不及讲

        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,//有最奇绝的峰峦
        A5,_,G5,_,E5,_,G5,D5,_,G5,_,_,C5,_,_,_,9,//
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,D6,_,_,E6,G6,_,E6,_,E6,_,_,Rest,_,_,9,//海上清辉与圆月
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,//
        A5,_,G5,_,E5,_,G5,A5,_,B5,_,_,A5,_,_,_,9,//
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,B5,_,_,B5,C6,_,B5,_,_,_,A5,_,_,_,_,_,_,9,//世人惊羡的桥段不过寻常

        Rest,Rest,Rest,

        A4,_,_,_,G4,_,A4,_,B4,_,C5,B4,_,G4,_,_,9,//光 是谁燃烛照亮
        A4,_,_,_,G4,_,A4,_,B4,_,C5,B4,_,F3,_,9,//时间设下的迷藏
        A4,_,_,_,G3,_,A4,_,B4,_,C5,B4,_,_,G4,_,_,_,Rest,A4,_,G4,E4,_,G4,_,_,9,//光 置换明暗立场 肆意流淌
        A4,_,_,_,G4,_,A4,_,B4,_,C5,B4,_,G4,_,_,9,//看 谁站过的地方
        A4,_,_,_,G4,_,A4,_,B4,_,C5,D5,_,C5,_,_,9,//棋局已百孔千疮
        A4,_,_,_,G4,_,A4,_,B4,_,C5,D5,_,B4,_,_,C5,_,_,Rest,B4,C5,_,_,_,9, //看眼前最真假相 假 又何妨
        C5,D5,E5,_,_,_,G5,_,G5,_,E5,D5,_,C5,_,_,9,//怀揣着炽烈顽心走向
        A4,_,E5,D5,_,C5,_,A4,_,_,_,9,//最宽容刑场
        Rest,G4,A4,_,E5,D5,_,E5,_,_,G5,_,E5,D5,_,C5,_,_,_,E5,_,_,Rest,_,9,//裂过碎过
        Rest,C5,D5,E5,_,_,E5,_,_,_,G5,_,G5,_,E5,D5,_,D5,_,_,9,//到最后
        A5,_,E5,D5,_,G5,_,_,C5,_,_,_,9,//仍留在身上
        Rest,_,G4,A4,_,E5,D5,_,E5,_,_,G5,_,_,A5,_,E5,_,G5,_,_,Rest,_,_,_,9,//来不及讲

        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,//有最奇绝的峰峦
        A5,_,G5,_,E5,_,G5,D5,_,G5,_,_,C5,_,_,_,9,//
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,D6,_,_,E6,G6,_,E6,_,E6,_,_,Rest,_,_,9,//海上清辉与圆月
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,//
        A5,_,G5,_,E5,_,G5,A5,_,B5,_,_,A5,_,_,_,9,//
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,B5,_,_,B5,C6,_,B5,_,_,_,A5,_,_,_,_,_,_,9,//世人惊羡的桥段不过寻常

        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,//有最奇绝的峰峦
        A5,_,G5,_,E5,_,G5,D5,_,G5,_,_,C5,_,_,_,9,//
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,D6,_,_,E6,G6,_,E6,_,E6,_,_,Rest,_,_,9,//海上清辉与圆月
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,//
        A5,_,G5,_,E5,_,G5,A5,_,B5,_,_,A5,_,_,_,9,//

        E5,_,G5,_,B5,_,B5,C6,_,B5,_,_,A5,_,_,9,//
        A5,_,G5,_,E5,_,G5,D5,_,G5,_,_,C5,_,_,_,9,//
        Rest,E5,G5,B5,_,_,E5,C6,_,B5,_,_,_,A5,_,_,9,
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,D6,_,_,E6,G6,_,E6,_,E6,_,_,Rest,_,_,9,
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,_,9,
        A5,_,G5,_,E5,_,G5,A5,_,B5,_,_,A5,_,_,_,9,
        E5,_,G5,_,A5,_,E6,D6,_,C6,_,_,B5,_,_,B5,C6,_,B5,_,_,_,_,A5,_,_,_,-999
  };

int main() {
    HMIDIOUT handle;
    midiOutOpen(&handle, 0, 0, 0, CALLBACK_NULL);
    midiOutShortMsg(handle, 0 << 8 | 0xC1); //设置通道0的乐器为 大钢琴
    unsigned short note = 0;    //音符编号
    unsigned short velocity = 110; // 力度值,范围通常在0-127
    unsigned char statusByte = 0x90 | (0 & 0x0F);//0为声道
    int c = 0;

    printf("准备开始播放《盗墓笔记-十年人间》\n"); printf("    "); for (int i = 0; i < 3; i++) { Sleep(1000); printf("-*-*"); }printf("\n");

    for (int i = 0; i - 1 < 1200; i++) {
        if (qu[i] == -999) { Sleep(2000); printf("\n播放结束\n"); break; }
        if (qu[i] == 9)
        {
            printf("%s", ci[c]);
            c++;
        }
        else {
            Sleep(190);
            if (qu[i] == '_')
            {
                Sleep(170);
            }
            else
            {
                note = qu[i];
            }
        }
        // 组合3个字节的消息到一个DWORD值
        unsigned long noteOnMsg = (((unsigned long)velocity << 16) | (((unsigned long)note) << 8) | (unsigned long)statusByte);
        // 发送MIDI消息
        midiOutShortMsg(handle, noteOnMsg);
    }
    midiOutClose(handle);

	return 0;
}

 基本的播放思路就是在数组中读取到音符就合成一个信息给到函数播放,遇到停顿和终止就执行相关操作。

  • 29
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值