最近开发了一款基于Android6.0系统的钢琴学习系统,本文将主要介绍MIDI协议的常识、Android MIDI 相关API的使用,以及MIDI应用程序开发需要借鉴的开源项目,最后分析本项目的架构。

本文的主要结构如下图所示:

本文项目架构

1.MIDI概述

1.1乐器数字接口

(Musical Instrument Digital Interface,简称MIDI)是一个工业标准的电子通信协议.为电子乐器等演奏设备(如合成器)定义各种音符或弹奏码,容许电子乐器、电脑、手机或其它的舞台演出配备彼此连接,调整和同步,得以即时交换演奏数据。MIDI不发送声音,只发送像是音调和音乐强度的数据,音量,颤音和相位[1]等参数的控制信号,还有设置节奏的时钟信号。在不同的电脑上,输出的声音也因音源器不同而有差异。

1.2 MIDI的优点

1.共通语言及语法:

键盘乐器,电子鼓,电脑,编曲机及其他为MIDI设计出来的特殊功能电子乐器之间可以轻易的相互链接

2.简化的链接:

减少了音乐设备之间导线、信号线链接的复杂性(如音量控制)

3.更少的演出者:

1980年代初期,音乐演出者可以仅靠一至两人进行现场演出,同时操作数台MIDI设备,制造出像交响乐团般的演出效果

4.更低的获取门槛:

用户可以以更少的花费创作、编辑、制作高质量的数字音乐。专业的音乐家可以在家里自己录音,宅录,不用花钱租录音室,也不用请一堆乐手来帮忙录音。同时更让没音乐基础的爱好者可以利用MIDI音乐软件高度扩充性进行高质量录音

5.方便可携的电子音乐器材:

大量减少了乐手巡回演出时所需携带的乐器、器材与线材的数量,在搬运、装载、架设器材也简易了许多,却仍可以制造出相当的音色与效果.

1.3 MIDI的运作过程

当MIDI播放器演奏了一个音符的时候,它随之将音符转换成MIDI信息。一个典型的由键盘获取的音符的MIDI信息的过程包括:

1.用户以特定速率(又译,力度-velocity)演奏中央C音符。

2.用户改变按压键盘按键的力度-这个技术称为键后触感(aftertouch)。

3.用户释放并停止演奏中央C音符。

2.Android Midi相关API

2.1用到的主要类在android.media.midi中,除此之外还要用到音频播放相关的API:AudioTrack,AudioRecord等相关API.

2.2接口 MidiManager.OnDeviceOpenedListener

/**    * Listener class used for receiving the results of {@link #openDevice} and    * {@link #openBluetoothDevice}    */    public interface OnDeviceOpenedListener {        /**        * Called to respond to a {@link #openDevice} request        *        * @param device a {@link MidiDevice} for opened device, or null if opening failed        */        abstract public void onDeviceOpened(MidiDevice device);    } 在调用Midimanger.openDevice(MidiDeviceInfo, MidiManager.OnDeviceOpenedListener, Handler)方法时需要传入这样一个接口,再回调函数里能够得到打开的设备MidiDevice

2.3相关类

2.3.1 MidiDevice该类属于Midi设备,该类的创建比较特殊,需要通过 openDevice(MidiDeviceInfo, MidiManager.OnDeviceOpenedListener, Handler)进行创建,在MidiManager.OnDeviceOpenedListener的回调中会得到该类1 MidiDeviceInfo getInfo ()2 MidiInputPort openInputPort (int portNumber)3 MidiOutputPort openOutputPort (int portNumber)这三个方法相对比较容易理解,主要用来得到设备的信息,通过端口号来打开一个输入端口和输出端口4 MidiDevice.MidiConnection connectPorts (MidiInputPort inputPort,                int outputPortNumber)这个方法相对比较特殊,主要用来将两个设备连接起来,第一个参数为需要连接的设备的输入端口,第二个参数为输出设备的输出端口号

2.3.2 MidiDevice.MidiConnection两个设备连接在一起的connection当需要断开连接时需要关闭对应的connection ,释放流和相应的系统资源,防止内存泄漏等

2.3.3 MidiDeviceInfoMidiDeviceInfo 包含了设备的所有物理信息的详细描述,而真正在不通设备之间建立连接的是MidiDevice.MidiDeviceInfo包含丰富的物理信息:PROPERTY_BLUETOOTH_DEVICEPROPERTY_MANUFACTURERPROPERTY_NAMEPROPERTY_PRODUCTPROPERTY_SERIAL_NUMBERPROPERTY_USB_DEVICEPROPERTY_VERSIONTYPE_BLUETOOTHTYPE_USBTYPE_VIRTUAL可以通过下面的方法传入不同的常量来获得对应的信息info.getProperties()                    .getString(MidiDeviceInfo.PROPERTY_MANUFACTURER);int getId ():返回设备的id号int getInputPortCount ():得到设备的输入端口的个数int getOutputPortCount ()得到设备输出端口的个数PortInfo[] getPorts ():返回设备的端口  ,返回的变量是一个数组,可能包含设备的输入端口和输出端口,PortInfo是MidiDeviceInfo的内部类,包含端口的信息,输入输出类型等Bundle getProperties ():返回一个bundle对象,可以用其或得设备的物理信息int getType ():得到设备的类型boolean isPrivate ():判断设备是否属于私有设备

2.3.4 MidiDeviceInfo.PortInfoString getName ()int getPortNumber ()int getType ()几个方法很容易理解分别返回端口的名字 端口号 以及输入输出类型

2.3.5 MidiDeviceServiceMidiDeviceService  继承于Service ,用于创建一个虚拟的Midi设备一般情况下,我们通过继承这个类去构建一个虚拟的Midi设备,继承这个类必须重写两个方法,分别用来接收其他Midi设备发出的信息,或者向其他设备发送信息  MidiReceiver[] onGetInputPortReceivers (),向service设备提供MidiReceiver 去接收信息  MidiReceiver[] getOutputPortReceivers () ,用来提供发送信息的MidiReceiver并且继承这个类必须在Manifest文件中进行注册我们可以定义该虚拟设备的制造商,产品  以及输入输出类型等信息MidiDeviceInfo getDeviceInfo ()得到该设备的信息void onDeviceStatusChanged (MidiDeviceStatus status)在设备的状态被改变时进行回调

2.3.6 MidiDeviceStatus1.MidiDeviceInfo getDeviceInfo ()能够通过状态改变的回调,得到设备的信息2.int getOutputPortOpenCount (int portNumber)假如该设备是一个输出设备,能够得到所有与该输出设备某端口(portNumbe)连接的设备的数量,一个输出设备能够同时被多个设备连接。3.boolean isInputPortOpen (int portNumber)假如该设备是一个输入设备,能够得到该输入设备的某个端口是否打开,一个输入设备,只能被一个设备连接

2.3.7 MidiInputPort

2.3.8 MidiManagerMidiManger 是MIDI设备的管理者 ,类似于PackgerManger MediaManger 等系统某一类的管理者,其得到的方式与其他Manger的得到方式类似:MidiManager manager = (MidiManager) getSystemService(Context.MIDI_SERVICE);几个常用的公用方法:1 MidiDeviceInfo[] getDevices ()  该方法能够返回 系统所连结的所有MIDI设备,系统能够识别多个不同的MIDI设备,甚至包括输入输出设备,并将这些设备的相关信息以数组的形式返回2 void openBluetoothDevice (BluetoothDevice bluetoothDevice,                MidiManager.OnDeviceOpenedListener listener,                Handler handler)  该方法表明系统可以连接通过蓝牙连接MIDI设备,假设该Midi设备支持蓝牙,因开发过程中没有此设备,没有做过测试,但蓝牙Midi设备的可扩展性、便携性无疑更强3 void openDevice (MidiDeviceInfo deviceInfo,                MidiManager.OnDeviceOpenedListener listener,                Handler handler) 该方法用来打开一个设备,需要传入被打开设备的信息 打开设备的回调接口 以及Handler4 void registerDeviceCallback (MidiManager.DeviceCallback callback,                Handler handler) 注册一个回调接口,用来检测设备的插入与连接,当设备被连接时,如果该设备有打开的端口, onDeviceStatusChanged(MidiDeviceStatus)方法会立刻被调用.5 void unregisterDeviceCallback (MidiManager.DeviceCallback callback) 注销回调接口

2.3.9 MidiManager.DeviceCallback当设备被连接时的回调:void onDeviceAdded (MidiDeviceInfo device)void onDeviceRemoved (MidiDeviceInfo device)void onDeviceStatusChanged (MidiDeviceStatus status)  分别对应设备插入 移除 状态改变的 notifaction 通知

2.3.10 MidiOutputPort

2.3.11 MidiReceiverMidiReceiver 用来接收来自Midi设备的信息或者向Midi设备发送信息1.int getMaxMessageSize () 返回MidiReceiver可以接受的信息的最大容量2 void onSend (byte[] msg,                int offset,                int count,                long timestamp)当信息被传递的时候被调用3 void send (byte[] msg,                int offset,                int count)用来发送信息(不包含发送时间)4 void send (byte[] msg,                int offset,                int count,                long timestamp)用来发送信息(包含时间戳)

2.3.12MidiSenderMidiSender 用来绑定Midi设备的MidiReceiver1 void connect (MidiReceiver receiver)用来连接某个MidiReceiver

2.2.4相关开源项目

https://github.com/googlesamples/android-MidiScope.git(只发送信息,不发声音)https://github.com/googlesamples/android-MidiSynth.git(能够检测设备,连接设备并发声)

3.项目架构项目架构及详细分析见项目源码

https://github.com/duanjiefei/MidiPaino.git

android midi 编辑6,Android6.0MIDI设备相关应用程序开发相关推荐

  1. linux一句话问答(网络无关篇+网络相关篇+程序开发篇+经典图书)

    一句话问答(网络无关篇+网络相关篇+程序开发篇+经典图书) --------------------------目录-网络无关篇-目录-------------------------- 0001 修 ...

  2. 二手手机设备回收小程序开发

    二手手机设备回收小程序开发 二手手机设备回收小程序开发是一个可以帮助用户在线完成二手手机设备交易的应用.它通过提供便捷的搜索和浏览功能,让用户快速找到自己需要的二手手机设备并进行购买或出售. 开发这样 ...

  3. 设备巡检小程序开发制作功能介绍

    巡检员可使用小程序生成不同类型的巡检表并选择巡检类型.项目评测包括了设备评测.险源控制等模块,方便巡检员及时记录数据,避免数据延误录入带来的麻烦.也方便企业管理者及时查看数据,及时改进问题. 设备巡检 ...

  4. android锁屏快捷键设置,Android4.0+锁屏程序开发——设置锁屏页面篇

    [如何开发一个锁屏应用] 想要开发一个锁屏应用,似乎很难,其实并没有想象中那么难. 从本质上来说,锁屏界面也只是一个Activity而已,只是这个界面比较特殊,在我们点亮屏幕的时候,这个界面就会出现. ...

  5. Xamarin设备相关图片尺寸要求

    Xamarin设备相关图片尺寸要求 Xamarin跨平台开发,要兼顾iOS.Android.尤其是图片方面,各个平台有对应的不同要求.在iOS中,需要提供没有后缀(设备无关单位尺寸).@2x(双倍像素 ...

  6. snmp获取设备相关管理信息

    snmp获取设备相关管理信息 在本文中,作者将向我们展示如何用snmp代理监视网络设备,甚至发送软件警告. 网络上很多代理在为我们服务.只要我们开启UDP/161,162端口,这些代理就会以Manag ...

  7. android midi字节,MIDI的20个基本概念

    原标题:MIDI的20个基本概念 Keyboard杂志老资格编辑Jim Aikin在纪念MIDI诞生20的时候发表一篇文章,讲述MIDI使用中经常遇到的20个概念,虽然都是"老生常谈&quo ...

  8. android权限编辑xml大全(中英文对照)

    程序执行需要读取到安全敏感项必需在androidmanifest.xml中声明相关权限请求, 完整列表如下: android.permission.ACCESS_CHECKIN_PROPERTIES ...

  9. 安卓(android)6.0高通平台下设备树专题视频讲解【全国独家+设备树视频教程】

    安卓(android)6.0高通平台下设备树专题视频讲解[全国独家+设备树视频教程]                                                      独家拥有 ...

最新文章

  1. Linux 交叉编译简介
  2. OpenCV 【四】————Watershed Algorithm(图像分割)——分水岭算法的原理及实现
  3. 英语计算机单词mp3,计算机英语会话(MP3+中英字幕) 第1期:计算机系统(1)
  4. Python3--批量爬取数据之调用百度api进行翻译
  5. 需求又变了,要不要怼回去?
  6. python交互式数据可视化_python数据可视化工具
  7. mysql字段中有逗号隔开_在MySQL字段中使用逗号分隔符
  8. F5:2022年应用交付和安全领域趋势展望
  9. MAC Photoshop标题栏不见了
  10. 数据链路层概述(主要解决的三个问题)
  11. CDGA|数据治理中数据如何分类分级呢?
  12. C语言期末复习题(带答案)
  13. Linux 磁盘管理 : mount 命令详解
  14. 第2节 二叉树计算欧式和美式期权价格
  15. Learning Rich Features at High-Speed for Single-Shot Object Detection
  16. 学校计算机机房应急预案,中心机房应急预案管理制度
  17. Bounding-box regression in RCNN/Faster-RCNN/SSD
  18. 电子计算机受周易启发,数学家眼里《周易》
  19. 康泰克采样器完整版-Native Instruments Kontakt v6.3.1 WIN/MAC
  20. 【观察】智能安防的新时代,华为的重构和创新

热门文章

  1. R语言可视化散点图、使用ggrepel包的geom_text_repel函数避免数据点之间的标签互相重叠(设置nudge_y参数和direction参数显示部分数据点的标签在可视化图像的顶部)
  2. spark 实现HDFS小文件合并
  3. HTML期末大作业~个人图片资源网页设计共5个页面(HTML+CSS+JavaScript)
  4. C++实例(八)菜单
  5. 腾讯智慧校园 php,【腾讯智慧校园1.54版本】发布
  6. 不用再等后端的接口啦!这个开源项目花 2 分钟就能模拟出后端接口
  7. 3D游戏建模在游戏公司中是什么样的角色?薪资高,有前途吗
  8. 西祠胡同社区彻底消失
  9. vue+photoswipe
  10. win7 php搭建博客,win7下wordPress本地搭建博客详解(深度亲测整理—傻瓜式详细教程) | 学步园...