C#演奏《不能说的秘密》《路小雨》,周杰伦

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace ConsoleApp2
{
class Program
{
//根据API引入外部函数,MIDI的三个主要函数,打开,操作,关闭
[DllImport("winmm.dll")]
private static extern int midiOutOpen(out int sirius_MidiOut, int uDeviceID, int dwCallback, int dwInstance, int dwFlags);
[DllImport("winmm.dll")]
private static extern int midiOutShortMsg(int hMidiOut, int dwMsg);
[DllImport("winmm.dll")]
private static extern int midiOutClose(int hMidiOut);
enum Scale //共有128个MIDI国际标准音高0-127,我们以大钢琴的88个音为基准建立枚举数值,中央C为小字一组c1,MIDI音高为60号。
{
Rest = 0,
A1 = 21, A1s = 22, B1 = 23,
C1 = 24, C1s = 25, D1 = 26, D1s = 27, E1 = 28, F1 = 29, F1s = 30, G1 = 31, G1s = 32, A = 33, As = 34, B = 35,
C = 36, Cs = 37, D = 38, Ds = 39, E = 40, F = 41, Fs = 42, G = 43, Gs = 44, a = 45, aS = 46, b = 47,
c = 48, cs = 49, d = 50, ds = 51, e = 52, f = 53, fs = 54, g = 55, gs = 56, a1 = 57, a1s = 58, b1 = 59,
c1 = 60, c1s = 61, d1 = 62, d1s = 63, e1 = 64, f1 = 65, f1s = 66, g1 = 67, g1s = 68, a2 = 69, a2s = 70, b2 = 71,//小字一组,c1为中央C,60号音高
c2 = 72, c2s = 73, d2 = 74, d2s = 75, e2 = 76, f2 = 77, f2s = 78, g2 = 79, g2s = 80, a3 = 81, a3s = 82, b3 = 83,
c3 = 84, c3s = 85, d3 = 86, d3s = 87, e3 = 88, f3 = 89, f3s = 90, g3 = 91, g3s = 92, a4 = 93, a4s = 94, b4 = 95,
c4 = 96, c4s = 97, d4 = 98, d4s = 99, e4 = 100, f4 = 101, f4s = 102, g4 = 103, g4s = 104, a5 = 105, a5s = 106, b5 = 107,
c5 = 108
};
enum Voice_majorC //C大调。上面的Scale更方便五线谱读谱,由于我们这里主要的依据是简谱,为了代码的可读性及其简化,所以再从Scale中选取以小字一组(c1-b2)为中音区的五个音区,X极低音,L低音,M中音,H高音,Y极高音。
{
X1 = Scale.C, X2 = Scale.D, X3 = Scale.E, X4 = Scale.F, X5 = Scale.G, X6 = Scale.a, X7 = Scale.b,//极低音
L1 = Scale.c, L2 = Scale.d, L3 = Scale.e, L4 = Scale.f, L5 = Scale.g, L6 = Scale.a1, L7 = Scale.b1,//低音区
M1 = Scale.c1, M2 = Scale.d1, M3 = Scale.e1, M4 = Scale.f1, M5 = Scale.g1, M6 = Scale.a2, M7 = Scale.b2,//中音区
H1 = Scale.c2, H2 = Scale.d2, H3 = Scale.e2, H4 = Scale.f2, H5 = Scale.g2, H6 = Scale.a3, H7 = Scale.b3,//高音区
Y1 = Scale.c3, Y2 = Scale.d3, Y3 = Scale.e3, Y4 = Scale.f3, Y5 = Scale.g3, Y6 = Scale.a4, Y7 = Scale.b4,//极高音
_ = 0XFF//空音
}
enum Voice_Bflatmajor//降b大调。以降b(我们这里写成了升A,#A,一个意思)为主音do,满足“全全半全全全半”的大调音程关系。
{
X1 = Scale.As, X2 = Scale.C, X3 = Scale.D, X4 = Scale.Ds, X5 = Scale.F, X6 = Scale.G, X7 = Scale.a,
L1 = Scale.aS, L2 = Scale.c, L3 = Scale.d, L4 = Scale.ds, L5 = Scale.f, L6 = Scale.g, L7 = Scale.a1,
M1 = Scale.a1s, M2 = Scale.c1, M3 = Scale.d1, M4 = Scale.d1s, M5 = Scale.f1, M6 = Scale.g1, M7 = Scale.a2,
H1 = Scale.a2s, H2 = Scale.c2, H3 = Scale.d2, H4 = Scale.d2s, H5 = Scale.f2, H6 = Scale.g2, H7 = Scale.a3,
Y1 = Scale.a3s, Y2 = Scale.c3, Y3 = Scale.d3, Y4 = Scale.d3s, Y5 = Scale.f3, Y6 = Scale.g3, Y7 = Scale.a4,
_=0XFF
}
enum Voice_Gmajor //G大调,以G为主音do,满足“全全半全全全半”的大调音程关系。
{
X1 = Scale.G, X2 = Scale.a, X3 = Scale.b, X4 = Scale.c, X5 = Scale.d, X6 = Scale.e, X7 = Scale.fs,
L1 = Scale.g, L2 = Scale.a1, L3 = Scale.b1, L4 = Scale.c1, L5 = Scale.d1, L6 = Scale.e1, L7 = Scale.f1s,
M1 = Scale.g1, M2 = Scale.a2, M3 = Scale.b2, M4 = Scale.c2, M5 = Scale.d2, M6 = Scale.e2, M7 = Scale.f2s,
H1 = Scale.g2, H2 = Scale.a3, H3 = Scale.b3, H4 = Scale.c3, H5 = Scale.d3, H6 = Scale.e3, H7 = Scale.f3s,
Y1 = Scale.g3, Y2 = Scale.a4, Y3 = Scale.b4, Y4 = Scale.c4, Y5 = Scale.d4, Y6 = Scale.e4, Y7 = Scale.f4s,
_ = 0XFF
}
static void Main(string[] args)
{
while (true)
{
Secret();
}
}
#region 《不能说的秘密》周杰伦
static void Secret()
{
Console.WriteLine("《不能说的秘密》\n演奏:竖琴伴奏,模拟人声喝唱\n代码作者:幽灵眼中的星星");
int[] bunengshuodemimi =//《不能说的秘密》音谱数组,G大调,4/4拍(以四分音符为一拍,每小节四拍),每分钟72拍,每拍约833ms。
{
//测试
250,(int)Voice_Gmajor.M1,(int)Voice_Gmajor.M2,(int)Voice_Gmajor.M3,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M6,(int)Voice_Gmajor.M7,(int)Voice_Gmajor.H1,
(int)Voice_Gmajor.M7,(int)Voice_Gmajor.M6,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M3,(int)Voice_Gmajor.M2,(int)Voice_Gmajor.M1,
(int)Voice_Gmajor._,(int)Voice_Gmajor._,(int)Voice_Gmajor._,(int)Voice_Gmajor._,(int)Voice_Gmajor._,
//part1
750,(int)Voice_Gmajor._,500,(int)Voice_Gmajor.L5,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,250,(int)Voice_Gmajor.M3,1250,(int)Voice_Gmajor.M3,
500,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M3,(int)Voice_Gmajor.M2,(int)Voice_Gmajor.M1,(int)Voice_Gmajor.L7,(int)Voice_Gmajor.L7,2500,(int)Voice_Gmajor.M1,
1750,(int)Voice_Gmajor._,250,(int)Voice_Gmajor.M5,500,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,250,(int)Voice_Gmajor.M4,1250,(int)Voice_Gmajor.M3,
500,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,250,(int)Voice_Gmajor.M4,750,(int)Voice_Gmajor.M4,500,(int)Voice_Gmajor.M3,(int)Voice_Gmajor.M3,2500,(int)Voice_Gmajor.M2,
1750,(int)Voice_Gmajor._,250,(int)Voice_Gmajor.L5,500,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,250,(int)Voice_Gmajor.M3,1250,(int)Voice_Gmajor.M3,
500,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M3,(int)Voice_Gmajor.M2,(int)Voice_Gmajor.M1,(int)Voice_Gmajor.L7,250,(int)Voice_Gmajor.L7,(int)Voice_Gmajor.M2,1500,(int)Voice_Gmajor.M1,2000,(int)Voice_Gmajor.M1,
//part2
1500,(int)Voice_Gmajor._,500,(int)Voice_Gmajor.L6,(int)Voice_Gmajor.M1,1000,(int)Voice_Gmajor.M5,500,(int)Voice_Gmajor.M6,(int)Voice_Gmajor.M1,2500,(int)Voice_Gmajor.M1,
500,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,250,(int)Voice_Gmajor.M5,750,(int)Voice_Gmajor.M5,500,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M3,(int)Voice_Gmajor.M3,2500,(int)Voice_Gmajor.M2,
//part3
1500,(int)Voice_Gmajor._,500,(int)Voice_Gmajor.M1,(int)Voice_Gmajor.H1,(int)Voice_Gmajor.M7,(int)Voice_Gmajor.H1,1000,(int)Voice_Gmajor.H1,500,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,1000,(int)Voice_Gmajor.M5,500,(int)Voice_Gmajor.M4,1000,(int)Voice_Gmajor.M4,
500,(int)Voice_Gmajor.M3,500,(int)Voice_Gmajor._,(int)Voice_Gmajor.M1,(int)Voice_Gmajor.H1,(int)Voice_Gmajor.M7,(int)Voice_Gmajor.H1,1000,(int)Voice_Gmajor.H1,500,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,1000,(int)Voice_Gmajor.M5,500,(int)Voice_Gmajor.M4,1000,(int)Voice_Gmajor.M4,
500,(int)Voice_Gmajor.M3,500,(int)Voice_Gmajor._,(int)Voice_Gmajor.H1,(int)Voice_Gmajor.H1,(int)Voice_Gmajor.M7,(int)Voice_Gmajor.H1,1000,(int)Voice_Gmajor.M7,750,(int)Voice_Gmajor.M6,250,(int)Voice_Gmajor._,500,(int)Voice_Gmajor.H1,(int)Voice_Gmajor.M7,(int)Voice_Gmajor.M6,(int)Voice_Gmajor.M7,1000,(int)Voice_Gmajor.M6,
750,(int)Voice_Gmajor.M5,250,(int)Voice_Gmajor._,500,(int)Voice_Gmajor.H1,(int)Voice_Gmajor.M6,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M6,1000,(int)Voice_Gmajor.M5,500,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M3,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M6,1000,(int)Voice_Gmajor.M6,
750,(int)Voice_Gmajor.M5,250,(int)Voice_Gmajor._,
//part3前两句重复
500,(int)Voice_Gmajor.M1,(int)Voice_Gmajor.H1,(int)Voice_Gmajor.M7,(int)Voice_Gmajor.H1,1000,(int)Voice_Gmajor.H1,500,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,1000,(int)Voice_Gmajor.M5,500,(int)Voice_Gmajor.M4,1000,(int)Voice_Gmajor.M4,
500,(int)Voice_Gmajor.M3,500,(int)Voice_Gmajor._,(int)Voice_Gmajor.M1,(int)Voice_Gmajor.H1,(int)Voice_Gmajor.M7,(int)Voice_Gmajor.H1,1000,(int)Voice_Gmajor.H1,500,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M5,1000,(int)Voice_Gmajor.M5,
500,(int)Voice_Gmajor.H2,1000,(int)Voice_Gmajor.H2,
500,(int)Voice_Gmajor.H1,500,(int)Voice_Gmajor._,(int)Voice_Gmajor.M1,(int)Voice_Gmajor.H1,(int)Voice_Gmajor.M7,(int)Voice_Gmajor.H1,1000,(int)Voice_Gmajor.M7,750,(int)Voice_Gmajor.M6,250,(int)Voice_Gmajor._,500,(int)Voice_Gmajor.M1,(int)Voice_Gmajor.M7,(int)Voice_Gmajor.M6,(int)Voice_Gmajor.M7,1000,(int)Voice_Gmajor.M6,
750,(int)Voice_Gmajor.M5,250,(int)Voice_Gmajor._,500,(int)Voice_Gmajor.M1,(int)Voice_Gmajor.M6,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M6,1000,(int)Voice_Gmajor.M5,500,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M3,(int)Voice_Gmajor.M4,(int)Voice_Gmajor.M5,(int)Voice_Gmajor.M6,1000,(int)Voice_Gmajor.M6,
750,(int)Voice_Gmajor.M5,250,(int)Voice_Gmajor._,500,(int)Voice_Gmajor.M4,1000,(int)Voice_Gmajor.M3,500,(int)Voice_Gmajor.L7,1000,(int)Voice_Gmajor.M2,3500,(int)Voice_Gmajor.M1
};
int sirius_MidiOut = 0;//设置MIDI设备句柄变量(播放时使用)
midiOutOpen(out sirius_MidiOut, 0, 0, 0, 0);//打开MIDI设备,将设备赋值给句柄变量
int volume = 0x7F;//设置音量最高,0-0x7F,0为最低音量。
int sleep = 833;//设置单个音的持续时长,默认为单拍时长。
int voice = 0x0;//定义需要MIDI播放的音的参数(非常重要)
foreach (var element in bunengshuodemimi)//遍历歌曲的音谱数组,播放每个音
{
//每个音播放前,设置空拍及音符持续时长标志,根据本乐曲设置,一拍为500ms
if (element == 250) { sleep = 208; continue; }//接下来的每个音时长为四分之一拍
if (element == 500) { sleep = 417; continue; }//接下来的每个音时长为半拍
if (element == 750) { sleep = 625; continue; }//接下来的每个音时长为四分之三拍
if (element == 1000) { sleep = 833; continue; }//接下来的每个音时长为一拍
if (element == 1250) { sleep = 1041; continue; }//接下来的每个音时长为一又四分之一,即1.25拍(连音线使用)
if (element == 1500) { sleep = 1250; continue; }//接下来的每个音时长为一拍半
if (element == 1750) { sleep = 1458; continue; }//接下来的每个音时长为一又四分之三,即1.75拍(连音线使用)
if (element == 2000) { sleep = 1666; continue; }//接下来的每个音时长为两拍
if (element == 2250) { sleep = 1874; continue; }//接下来的每个音时长为二又四分之一,即2.25拍(连音线使用)
if (element == 2500) { sleep = 2083; continue; }//接下来的每个音时长为两拍半
if (element == 3000) { sleep = 2499; continue; }//接下来的每个音时长为三拍
if (element == 3500) { sleep = 2916; continue; }//接下来的每个音时长为三拍半
if (element == 4000) { sleep = 3332; continue; }//接下来的每个音时长为四拍
voice = (volume << 16) + (element << 8) + 0x90;//设置需要播放的音的参数,volume为音量,element为需要播放的音高(来自音谱数组元素),0x91,9为开始吹奏,1为在第一个声音通道进行(通道从0x90-0x9F,共16个通道,都可以使用)。
midiOutShortMsg(sirius_MidiOut, 54 << 8 | 0xC0);//设置音色(我这里是合成人声,编号为54,可以查MIDI音色表,100多种声音都可以用),0xC1,C为设置,被设置的通道为1通道(通道从0xC0-0xCF,共16个通道,都可以设置)
midiOutShortMsg(sirius_MidiOut, voice);//吹奏voice代表的音
voice = (0x60 << 16) + (element << 8) + 0x91;//竖琴音道
Console.WriteLine(voice);
midiOutShortMsg(sirius_MidiOut, 46 << 8 | 0xC1);//竖琴
midiOutShortMsg(sirius_MidiOut, voice);//吹奏voice代表的音
Thread.Sleep(sleep);//音符持续时长
midiOutShortMsg(sirius_MidiOut, (volume << 16) + (element << 8) + 0x80);//停止该音的吹奏
midiOutShortMsg(sirius_MidiOut, (0x60 << 16) + (element << 8) + 0x81);//停止该音的吹奏
}
midiOutClose(sirius_MidiOut);//关闭MIDI设备
}
#endregion
}
}