Musical Instrument Digital Interface (MIDI) protocol是乐器(instruments),控制器(controllers)和电脑(computers)之间的的通信协议
MIDI不直接发送音频信号,而是发送event messages,包含了musical notes,controller signals(volume,vibrato,panning,cues,clock signals)来设置tempo等。

Web MIDI API 将不会实现高级的概念,比如sequencing,不直接支持 MIDI文件(MIDI播放器可以使用Web MIDI API创建)

requestMIDIAccess()

The feature name for requestMIDIAccess() is midi

partial interface Navigator {[SecureContext] Promise <MIDIAccess> requestMIDIAccess(optional MIDIOptions options = {});
};

MIDIOptions Dictionary

dictionary MIDIOptions {boolean sysex;boolean software;
};

MIDIInputMap Interface

[SecureContext, Exposed=Window] interface MIDIInputMap {readonly maplike <DOMString, MIDIInput>;
};

This type is used to represent all the currently available MIDI input ports.

// to tell how many entries there are:
var numberOfMIDIInputs = inputs.size;// add each of the ports to a <select> box
inputs.forEach( function( port, key ) {var opt = document.createElement("option");opt.text = port.name;document.getElementById("inputportselector").add(opt);
});

MIDIOutputMap Interface

[SecureContext, Exposed=Window] interface MIDIOutputMap {readonly maplike <DOMString, MIDIOutput>;
};

This type is used to represent all the currently available MIDI output ports. This enables:

// to tell how many entries there are:
var numberOfMIDIOutputs = outputs.size;// add each of the ports to a <select> box
outputs.forEach( function( port, key ) {var opt = document.createElement("option");opt.text = port.name;document.getElementById("outputportselector").add(opt);
});

MIDIAccess Interface

provides the methods to list MIDI input and output devices, and obtain access to an individual device

[SecureContext, Exposed=Window] interface MIDIAccess: EventTarget {readonly attribute MIDIInputMap inputs;readonly attribute MIDIOutputMap outputs;attribute EventHandler onstatechange;readonly attribute boolean sysexEnabled;
};
属性 描述
inputs MIDI输入
outputs MIDI输出
onstatechange 新的端口连接,或者已有的端口变化
sysexEnabled

MIDIPort Interface

This interface represents a MIDI input or output port.

[SecureContext, Exposed=Window] interface MIDIPort: EventTarget {readonly attribute DOMString id;readonly attribute DOMString? manufacturer;readonly attribute DOMString? name;readonly attribute MIDIPortType type;readonly attribute DOMString? version;readonly attribute MIDIPortDeviceState state;readonly attribute MIDIPortConnectionState connection;attribute EventHandler onstatechange;Promise <MIDIPort> open();Promise <MIDIPort> close();
};
属性 描述
id A unique ID of the port
manufacturer 端口的生产商
name 端口的名称
type 输入(input)或输出(output)的标志
version
state disconnected 或 connected
connection open 或 close 或 pending
onstatechange
open 打开端口
close 关闭端口

MIDIInput Interface

[SecureContext, Exposed=Window] interface MIDIInput: MIDIPort {attribute EventHandler onmidimessage;
};

MIDIOutput Interface

[SecureContext, Exposed=Window] interface MIDIOutput : MIDIPort {void send(sequence<octet> data, optional DOMHighResTimeStamp timestamp = 0);void clear();
};

MIDIMessageEvent Interface

[SecureContext, Exposed=Window]
interface MIDIMessageEvent : Event {constructor(DOMString type, optional MIDIMessageEventInit eventInitDict = {});readonly attribute Uint8Array data;
};

例子

获得midi接口

var midi = null;  // global MIDIAccess objectfunction onMIDISuccess( midiAccess ) {//如果连接midi设备成功console.log( "MIDI ready!" );midi = midiAccess;  // store in the global (in real usage, would probably keep in an object instance)
}function onMIDIFailure(msg) {//如果连接midi设备失败console.log( "Failed to get MIDI access - " + msg );
}navigator.requestMIDIAccess().then( onMIDISuccess, onMIDIFailure );

获得midi的输入和输出端口

function listInputsAndOutputs( midiAccess ) {for (var entry of midiAccess.inputs) {var input = entry[1];console.log( "Input port [type:'" + input.type + "'] id:'" + input.id +"' manufacturer:'" + input.manufacturer + "' name:'" + input.name +"' version:'" + input.version + "'" );}for (var entry of midiAccess.outputs) {var output = entry[1];console.log( "Output port [type:'" + output.type + "'] id:'" + output.id +"' manufacturer:'" + output.manufacturer + "' name:'" + output.name +"' version:'" + output.version + "'" );}
}

操作MIDI的输入

function onMIDIMessage( event ) {var str = "MIDI message received at timestamp " + event.timestamp + "[" + event.data.length + " bytes]: ";for (var i=0; i<event.data.length; i++) {str += "0x" + event.data[i].toString(16) + " ";}console.log( str );
}function startLoggingMIDIInput( midiAccess, indexOfPort ) {midiAccess.inputs.forEach( function(entry) {entry.onmidimessage = onMIDIMessage;});
}

操作MIDI的输出

function sendMiddleC( midiAccess, portID ) {var noteOnMessage = [0x90, 60, 0x7f];    // note on, middle C, full velocityvar output = midiAccess.outputs.get(portID);output.send( noteOnMessage );  //omitting the timestamp means send immediately.output.send( [0x80, 60, 0x40], window.performance.now() + 1000.0 ); // Inlined array creation- note off, middle C,// release velocity = 64, timestamp = now + 1000ms.
}
var context=null;   // the Web Audio "context" object
var midiAccess=null;  // the MIDIAccess object.
var oscillator=null;  // the single oscillator
var envelope=null;    // the envelope for the single oscillator
var attack=0.05;      // attack speed
var release=0.05;   // release speed
var portamento=0.05;  // portamento/glide speed
var activeNotes = []; // the stack of actively-pressed keyswindow.addEventListener('load', function() {// patch up prefixeswindow.AudioContext=window.AudioContext||window.webkitAudioContext;context = new AudioContext();if (navigator.requestMIDIAccess)navigator.requestMIDIAccess().then( onMIDIInit, onMIDIReject );elsealert("No MIDI support present in your browser.  You're gonna have a bad time.")// set up the basic oscillator chain, muted to begin with.oscillator = context.createOscillator();oscillator.frequency.setValueAtTime(110, 0);envelope = context.createGain();oscillator.connect(envelope);envelope.connect(context.destination);envelope.gain.value = 0.0;  // Mute the soundoscillator.start(0);  // Go ahead and start up the oscillator
} );function onMIDIInit(midi) {midiAccess = midi;var haveAtLeastOneDevice=false;var inputs=midiAccess.inputs.values();for ( var input = inputs.next(); input && !input.done; input = inputs.next()) {input.value.onmidimessage = MIDIMessageEventHandler;haveAtLeastOneDevice = true;}if (!haveAtLeastOneDevice)alert("No MIDI input devices present.  You're gonna have a bad time.");
}function onMIDIReject(err) {alert("The MIDI system failed to start.  You're gonna have a bad time.");
}function MIDIMessageEventHandler(event) {// Mask off the lower nibble (MIDI channel, which we don't care about)switch (event.data[0] & 0xf0) {case 0x90:if (event.data[2]!=0) {  // if velocity != 0, this is a note-on messagenoteOn(event.data[1]);return;}// if velocity == 0, fall thru: it's a note-off.  MIDI's weird, y'all.case 0x80:noteOff(event.data[1]);return;}
}function frequencyFromNoteNumber( note ) {return 440 * Math.pow(2,(note-69)/12);
}function noteOn(noteNumber) {activeNotes.push( noteNumber );oscillator.frequency.cancelScheduledValues(0);oscillator.frequency.setTargetAtTime( frequencyFromNoteNumber(noteNumber), 0, portamento );envelope.gain.cancelScheduledValues(0);envelope.gain.setTargetAtTime(1.0, 0, attack);
}function noteOff(noteNumber) {var position = activeNotes.indexOf(noteNumber);if (position!=-1) {activeNotes.splice(position,1);}if (activeNotes.length==0) {  // shut off the envelopeenvelope.gain.cancelScheduledValues(0);envelope.gain.setTargetAtTime(0.0, 0, release );} else {oscillator.frequency.cancelScheduledValues(0);oscillator.frequency.setTargetAtTime( frequencyFromNoteNumber(activeNotes[activeNotes.length-1]), 0, portamento );}
}

参考:
https://webaudio.github.io/web-midi-api/#midiaccess-interface

Web MIDI API W3C相关推荐

  1. Web MIDI简介

    "有关Web MIDI的教程? 在2016年? 你开玩笑的对吧?" 没有! 这不是你的想法! 对于我们自1990年代以来一直使用网络的用户来说," Web MIDI&qu ...

  2. Web MIDI 入门:如何用电子钢琴做一款游戏

    译注:本文是作者 Peter Anglea 发布在 <SmashingMagazine>上的一篇介绍 Web MIDI API 及用其开发一款电子钢琴游戏的文章.(转载请注明出处) 原文链 ...

  3. Web性能API——帮你分析Web前端性能

    开发一个现代化的互联网网站是一项复杂的任务,需要各种职能的密切合作以应对用户日新月异的需求.其中,网页的性能直接决定了用户的体验,而随着新型客户端浏览设备的出现与网站功能的日益复杂化,对于性能的专注也 ...

  4. 【Web】1326- 深入浅出 Web Audio API

    前言 2011被提出,同年草案被Google Chrome和Mozilla Firefox实现 在此之前Web音频较为原始,无法应付较为复杂的应用场景,例如Web游戏或互动应用 旨在提供全套Web音频 ...

  5. Java web speach api_HTML5 Web Speech API,让网站更有趣

    Web API 变得越来越丰富,其中一个值得注意的是Web Speech API.传统的网站只能"说",这个API的出现,让网站能"倾听"用户.这个功能已经开放 ...

  6. 利用 Web Share API 将网页分享到 App(上)

    2013年加入去哪儿网技术团队,目前在大住宿事业部,技术委员会委员,大前端负责人.个人对移动端技术.工程化有浓厚兴趣. 随着移动互联网的发展,用户流量逐渐从 PC 上迁移到了手机上,为了更好的满足移动 ...

  7. web audio api_带有Web Audio API的动态声音

    web audio api This article is part of a web dev series from Microsoft. Thank you for supporting the ...

  8. Web Audio API实现简单变声效果

    前言 想在网页中实现实时音频变声效果该如何实现呢,之前遇到这种处理音视频的需求,可能会想到需要借助C代码实现.但是现在随着浏览器性能的提升.web API的丰富,通过浏览器原生的API也可以操作音频数 ...

  9. 如何使用Web Audio API听到“ Yanny”和“ Laurel”的声音

    by _haochuan 通过_haochuan 如何使用Web Audio API听到" Yanny"和" Laurel"的声音 (How you can h ...

最新文章

  1. LINUX创建www的用户组和用户,并且不允许登录权限:
  2. html 找不到文件,WebView 加载本地HTML 文件 提示找不到该文件
  3. [JSP暑假实训] 三.MySQL数据库基本操作及Servlet网站连接显示数据库信息
  4. 办公技巧:Excel教程36个逆天功能,全面了解一下!
  5. 前端学习(95):ps基本操作与图片格式
  6. 线程切换是如何给 CPU 洗脑的?
  7. 多实例linux自动启动,Linux 下自动启动多个oracle实例
  8. 关于生命周期函数dealloc的使用小结
  9. 【面经】字节算法面试三面
  10. 三分钟了解APS系统中生产计划排程模块的基本原理
  11. 四款优秀的源代码扫描工具简介
  12. python任务栏显示网速_win10状态栏显示网速小工具_超好用
  13. Mybatis学习教程②
  14. 巨星陨落 - Jim Gary
  15. 如何创建一张属于自己的简单的网页
  16. 2022年淘宝女王节预售活动时间介绍
  17. Pandas处理大数据的性能优化技巧
  18. 1、张龙netty学习 第一个netty服务端
  19. Vue全家桶入门精细讲解
  20. 啪啪打脸,国际互联网协会数据泄露

热门文章

  1. 国际旅游管理专业跨专业考计算机,第二年跨校跨专业考旅游管理公费成功,一点经验给大家...
  2. asp.net session 如何知道是哪个浏览器客户端_小弟该如何复习 Java?
  3. 14、查找最接近的元素
  4. 基于android4的第三方系统,神速!第三方开发者放出小米3/4原生Android Oreo刷机包...
  5. 微课--Python正则表达式语法与应用(83分钟)
  6. Python使用matplotlib设置pandas绘制的饼状图扇形标签
  7. Python花式编程案例锦集(2)
  8. 5 批量更新多条记录_如何使用 F12 开发者工具自动批量删除新浪微博
  9. Linux 原来实现一个shell这么容易!(史上最简单详细)
  10. 程序员出差是去干什么_为什么女生不适合做程序员?原来互联网公司女生少,是由于这几点...