android设备开发流程,Android6.0MIDI设备相关应用程序开发

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

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

62e95d170a16

本文项目架构

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

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值