调用API让声卡发出声音
2021-07-16 18:23
1.定义一个枚举,乐器类型
#region 乐器定义
public enum MusicNo:uint
{ ///
/// //大钢琴
///
AcousticGrandPiano = 0,
///
///明亮的钢琴
///
BrightAcousticPiano = 1,
///
///电子琴
///
ElectricGrandPiano = 2,
///
///酒吧钢琴
///
HonkyTonkPiano = 3,
///
///柔和钢琴
///
RhodesPiano = 4,
///
///合唱效果钢琴
///
ChorusedPiano = 5,
///
///羽管键琴
///
Harpsichord = 6,
///
///克拉维科特琴
///
Clavichord = 7,
///
///钢片琴
///
Celesta = 8,
///
///钟琴
///
Glockenspiel = 9,
///
///八音盒
///
Musicbox = 10,
///
///颤音琴
///
Vibraphone = 11,
///
///马林巴
///
Marimba = 12,
///
///木琴
///
Xylophone = 13,
///
///管钟
///
TubularBells = 14,
///
///大扬琴
///
Dulcimer = 15,
///
/// 击杆风琴
///
HammondOrgan = 16,
///
/// 打击式风琴
///
PercussiveOrgan = 17,
///
/// 摇滚风琴
///
RockOrgan = 18,
///
/// 教堂风琴
///
ChurchOrgan = 19,
///
/// 簧管风琴
///
ReedOrgan = 20,
///
/// 手风琴
///
Accordian = 21,
///
/// 口琴
///
Harmonica = 22,
///
///探戈手风琴
///
TangoAccordian = 23,
///
/// 尼龙弦吉他
///
AcousTicGuitarNylon = 24,
///
/// 钢弦吉他
///
AcousTicGuitarSteel = 25,
///
/// 爵士电吉他
///
ElectricGuitarJazz = 26,
///
/// 清音电吉他
///
ElectricGuitarClean = 27,
///
/// 闷音电吉他
///
ElectricGuitarMuted = 28,
///
/// 加驱动效果的电吉他
///
OverdrivenGuitar = 29,
///
/// 加失真效果的电吉他
///
DistortionGuitar = 30,
///
/// 吉他和音
///
GuitarHarmonics = 31,
///
///大贝司(声学贝司)
///
AcousticBass = 32,
///
/// 电贝司(指弹)
///
ElectricBassfinger = 33,
///
/// 电贝司(拨片)
///
ElectricBassPick = 34,
///
/// 无品贝司
///
FretlessBass = 35,
///
/// 掌击Bass 1
///
SlapBass1 = 36,
///
/// 掌击Bass 2
///
SlapBass2 = 37,
///
/// 电子合成Bass 1
///
SynthBass1 = 38,
///
/// 电子合成Bass 2
///
SynthBass2 = 39,
///
/// 小提琴
///
Violin = 40,
///
/// 中提琴
///
Viola = 41,
///
/// 大提琴
///
Cello = 42,
///
/// 低音大提琴
///
Contrabass = 43,
///
///弦乐群颤音音色
///
TremoloStrings = 44,
///
///弦乐群拨弦音色
///
PizzicatoStrings = 45,
///
///竖琴
///
OrchestralHarp = 46,
///
/// 定音鼓
///
Timpani = 47,
///
///弦乐合奏音色1
///
StringEnsemble1 = 48,
///
///弦乐合奏音色2
///
StringEnsemble2 = 49,
///
///合成弦乐合奏音色1
///
SynthStrings1 = 50,
///
///合成弦乐合奏音色2
///
SynthStrings2 = 51,
///
///人声合唱“啊”
///
ChoirAahs = 52,
///
///人声“嘟”
///
VoiceOohs = 53,
///
///合成人声
///
SynthVoice = 54,
///
///管弦敲击齐奏
///
OrchestraHit = 55,
///
///小号
///
Trumpet = 56,
///
///长号
///
Trombone = 57,
///
///大号
///
Tuba = 58,
///
///加弱音器小号
///
MutedTrumpet = 59,
///
///法国号(圆号)
///
FrenchHorn = 60,
///
///铜管组(铜管乐器合奏音色)
///
BrassSection = 61,
///
///合成铜管音色1
///
SynthBrass1 = 62,
///
///合成铜管音色2
///
SynthBrass2 = 63,
///
///高音萨克斯风
///
SopranoSax = 64,
///
///次中音萨克斯风
///
AltoSax = 65,
///
///中音萨克斯风
///
TenorSax = 66,
///
///低音萨克斯风
///
BaritoneSax = 67,
///
///双簧管
///
Oboe = 68,
///
///英国管
///
EnglishHorn = 69,
///
///巴松(大管)
///
Bassoon = 70,
///
///单簧管(黑管)
///
Clarinet = 71,
///
///短笛
///
Piccolo = 72,
///
///长笛
///
Flute = 73,
///
///竖笛
///
Recorder = 74,
///
///排箫
///
PanFlute = 75,
///
///[中文名称暂缺]
///
BottleBlow = 76,
///
///日本尺八
///
Shakuhachi = 77,
///
///口哨声
///
Whistle = 78,
///
///奥卡雷那
///
Ocarina = 79,
///
///合成主音1(方波)
///
Lead1Square = 80,
///
///合成主音2(锯齿波)
///
Lead2Sawtooth = 81,
///
///合成主音3
///
Lead3CaliopeLead = 82,
///
///合成主音4
///
Lead4ChiffLead = 83,
///
///合成主音5
///
Lead5Charang = 84,
///
///合成主音6(人声)
///
Lead6Voice = 85,
///
///合成主音7(平行五度)
///
Lead7Fifths = 86,
///
///合成主音8(贝司加主音)
///
Lead8BassLead = 87,
///
///合成音色1(新世纪)
///
Pad1NewAge = 88,
///
///合成音色2 (温暖)
///
Pad2Warm = 89,
///
///合成音色3
///
Pad3Polysynth = 90,
///
///合成音色4 (合唱)
///
Pad4Choir = 91,
///
///合成音色5
///
Pad5Bowed = 92,
///
///合成音色6 (金属声)
///
Pad6Metallic = 93,
///
///合成音色7 (光环)
///
Pad7Halo = 94,
///
///合成音色8
///
Pad8Wweep = 5,
///
///合成效果 1 雨声
///
FX1Rain = 96,
///
///合成效果 2 音轨
///
FX2Soundtrack = 97,
///
///合成效果 3 水晶
///
FX3Crystal = 98,
///
///合成效果 4 大气
///
FX4Atmosphere = 99,
///
///合成效果 5 明亮
///
FX5Brightness = 100,
///
///合成效果 6 鬼怪
///
FX6Goblins = 101,
///
///合成效果 7 回声
///
FX7Echoes = 102,
///
///合成效果 8 科幻
///
FX8Scifi = 103,
///
///西塔尔(印度)
///
Sitar = 104,
///
///班卓琴(美洲)
///
Banjo = 105,
///
///三昧线(日本)
///
Shamisen = 106,
///
///十三弦筝(日本)
///
Koto = 107,
///
///卡林巴
///
Kalimba = 108,
///
///风笛
///
Bagpipe = 109,
///
///民族提琴
///
Fiddle = 110,
///
///山奈
///
Shanai = 111,
///
/// 叮当铃
///
TinkleBell = 112,
///
///[中文名称暂缺]
///
Agogo = 113,
///
///钢鼓
///
SteelDrums = 114,
///
///木鱼
///
Woodblock = 115,
///
///太鼓
///
TaikoDrum = 116,
///
///通通鼓
///
MelodicTom = 117,
///
///合成鼓
///
SynthDrum = 118,
///
///铜钹
///
ReverseCymbal = 119,
///
///吉他换把杂音
///
GuitarFretNoise = 120,
///
///呼吸声
///
BreathNoise = 121,
///
///海浪声
///
Seashore = 122,
///
///鸟鸣
///
BirdTweet = 123,
///
///电话铃
///
TelephoneRing = 124,
///
///直升机
///
Helicopter = 125,
///
///鼓掌
///
Applause = 126,
///
/// Gunshot
///
Gunshot = 127,
}
2.callback
public enum OpenFlag:uint
{
CALLBACK_NULL = 0x00000000,//{当 dwCallback 是 nil 时指定}
CALLBACK_WINDOW = 0x00010000,//{当 dwCallback 是窗口句柄时指定}
CALLBACK_FUNCTION = 0x0003000,// {当 dwCallback 是函数指针时指定}
}
3.打开设备返回值
public enum OpenMsg:uint
{
MMSYSERR_BADDEVICEID = 2,//{设备ID超界}
MMSYSERR_ALLOCATED = 4, //{指定的资源已被分配}
MMSYSERR_NOMEM = 7, //{不能分配或锁定内存}
MIDIERR_NOMAP = 66,//{当前没有 MIDI 映射, 只有打开映射程序才可能发生}
MIDIERR_NODEVICE = 68,//{MIDI 映射中的端口不存在, 只有打开映射程序才可能发生}
}
#endregion
4.midi帮助类
public class MIDIHelper
{
#region API
[DllImport("winmm.dll")]
static extern uint midiOutOpen(out IntPtr lphMidiOut, uint uDeviceID, IntPtr dwCallback, IntPtr dwInstance, uint dwFlags);//打开数字乐器接口输出
[DllImport("winmm.dll")]
static extern uint midiOutClose(IntPtr hMidiOut);//关闭数字乐器接口输出
[DllImport("winmm.dll")]
static extern uint midiOutShortMsg(IntPtr hMidiOut, uint dwMsg);//发送数字乐器接口消息
#endregion
5.定义变量
#region 自定义变量
bool isOpen = false;
IntPtr DeviceHandle = IntPtr.Zero;
public bool Opend => isOpen;
#endregion
#region 方法
6.打开设备。
public void Open()
{
IntPtr device;//此处后续要用
uint hand = midiOutOpen(out device, 0, IntPtr.Zero, IntPtr.Zero, 0);
isOpen = hand == 0;
DeviceHandle = device;
}
///
/// 播放声音返回0表示成功!621表示设备未打开
///
///
///
public uint Play(uint msg,int time)//播放,尝试了很多写法,发现msg * 256 + 0x00403B90;基本正常,百度百科的方法声音沙哑(msg*256+144+volume*655536+channel)
{
if (isOpen && DeviceHandle != IntPtr.Zero)
{
uint data = msg * 256 + 0x00403B90;
Console.WriteLine(data);
uint ms = midiOutShortMsg(DeviceHandle,data);
System.Threading.Thread.Sleep(time);
return msg;
}
else
return 621;
}
public uint ChangeInstruments(MusicNo musicNo)//改变乐器
{
return midiOutShortMsg(DeviceHandle, Convert.ToUInt32(192 + (uint)musicNo * 256));
}
public void Close()//关闭设备
{
uint msg = midiOutClose(DeviceHandle);
}
#endregion
}
接下来看看调用例子:
其中play方法中的数据12,50,...............摘自网上
MIDIHelper helper = new Gaofajin.Shell.MIDIHelper();
helper.Open();
if (helper.Opend)
{
helper.ChangeInstruments(Gaofajin.Shell.MusicNo.Piccolo);
helper.Play(12, 250);
helper.Play(12, 250);
helper.Play(15, 250);
helper.Play(17, 250);
helper.Play(19, 1000);
helper.Play(24, 700);
helper.Play(19, 250);
helper.Play(22, 200);
helper.Play(00, 250);
helper.Play(22, 900);
helper.Play(19, 400);
helper.Play(17, 400);
helper.Play(19, 400);
helper.Play(22, 400);
helper.Play(24, 250);
helper.Play(22, 250);
helper.Play(19, 1500);
helper.Play(00, 300);
helper.Play(19, 1000);
helper.Play(24, 700);
helper.Play(19, 250);
helper.Play(22, 200);
helper.Play(00, 250);
helper.Play(22, 900);
helper.Play(19, 400);
helper.Play(17, 400);
helper.Play(19, 400);
helper.Play(22, 400);
helper.Play(24, 250);
helper.Play(22, 250);
helper.Play(19, 1000);
helper.Play(00, 300);
helper.Play(19, 400);
helper.Play(17, 250);
helper.Play(15, 600);
helper.Play(00, 100);
helper.Play(15, 250);
helper.Play(17, 400);
helper.Play(19, 400);
helper.Play(17, 100);
helper.Play(00, 250);
helper.Play(17, 500);
helper.Play(00, 100);
helper.Play(17, 400);
helper.Play(15, 250);
helper.Play(12, 250);
helper.Play(00, 100);
helper.Play(12, 250);
helper.Play(15, 250);
helper.Play(17, 400);
helper.Play(19, 400);
helper.Play(22, 600);
helper.Play(24, 250);
helper.Play(22, 400);
helper.Play(19, 250);
helper.Play(17, 250);
helper.Play(15, 600);
helper.Play(17, 600);
helper.Play(19, 400);
helper.Play(17, 150);
helper.Play(00, 250);
helper.Play(17, 600);
helper.Play(15, 600);
helper.Play(12, 300);
helper.Play(00, 100);
helper.Play(12, 250);
helper.Play(15, 250);
helper.Play(17, 250);
helper.Play(19, 400);
helper.Play(22, 250);
helper.Play(24, 700);
helper.Play(00, 100);
helper.Play(24, 500);
}
helper.Close();