关于javax.sound.midi包的一些浅层探究(三)
来源:互联网 发布:博世待遇怎么样 知乎 编辑:程序博客网 时间:2024/05/29 17:35
接上篇讲,当顺利捕获了某一时刻的MidiMessage之后,我们该怎样对捕获的信息进行处理呢,我们又怎么知道当前产生的这个信息代表什么呢。
我们先来看看MidiMessage提供了哪些方法:
int length = msg.getLength(); // 获取MIDI数据长度byte[] data = msg.getMessage(); // 获取MIDI信息所包含的数据int status = msg.getStatus(); // 获取MIDI状态码
如果要判断midi信息的实际作用的话,要用到的就是getStatus()所取得的状态码了,在javax.sound.midi.ShortMessage类下有如下常量定义(只列出常见的)。
public static final int NOTE_OFF = 0x80; // 128 - 终止指定音符的播放public static final int NOTE_ON = 0x90; // 144 - 开始指定音符的播放public static final int CONTROL_CHANGE = 0xB0; // 176 - 改变轨道控制public static final int PROGRAM_CHANGE = 0xC0; // 192 - 变更音色
其中关于第三、四个只是在播放过程中经常捕获到,具体作用并未研究。
但在实际的开发过程中,我注意到一点。getStatus()函数返回的经常是一些完全对不上号的值。比如129,147之类。这是怎么一回事呢?
在研读过ShortMessage的源代码之后,我发现了一个有趣的地方:
public void setMessage(int command, int channel, int data1, int data2) throws InvalidMidiDataException { if (command >= 0xF0 || command < 0x80) { throw new InvalidMidiDataException("command out of range: 0x" + Integer.toHexString(command)); } if ((channel & 0xFFFFFFF0) != 0) { // <=> (channel<0 || channel>15) throw new InvalidMidiDataException("channel out of range: " + channel); } setMessage((command & 0xF0) | (channel & 0x0F), data1, data2); // 构造信息}以上是ShortMessage当中的setMessage函数,用来设置当前midi信息的属性,稍加观察我们便可以发现这一点:
setMessage((command & 0xF0) | (channel & 0x0F), data1, data2);
在这个地方,setMessage函数传入的command(代表midi命令)和channel(代表midi轨道)值被进行了一次或运算,一起存入了一个int值当中。
这也就不奇怪为什么midi标准当中规定“音轨编号从0-127” 而我们在上面看到的midi状态码第二位(也就是最后的8个比特位)是0了。
于是很容易想到从getStatus()获取的值中提取midi命令和midi轨道的具体值的方式,写作函数:
private int[] decryptStatus(int status) {int command = status & 0xF0;int channel = status & 0x0F;return new int[] { command, channel };}接下来,我们专门来看号码为128和144的midi命令,也就是开始/停止播放音符命令。
从上面的setMessage函数就可以明显看出,除了制定命令和音轨以外,还有data1和data2两个整形参数。那么它们分别代表什么呢?
在查阅了midi的标准手册以后,我发现,midi信号的接下来两个数分别代表的是指定的音符和使用的乐器。midi音符的表示方式如下表:
其中第60号就是我们一般所说的“中央C”,也就是最普遍的“duo”。从它开始数值加一或减一代表升一个半音或者降一个半音。
(如果对此不够清楚可以去稍微了解一下乐谱有关的知识)
而“乐器”则是指midi里规定的标准乐器,关于每个数分别代表什么乐器,底下有一个我从fl studio截下来的图:
当然,在百度百科的midi介绍页面上也有列出。
有了上面这些基础认识,我们就可以对midi进行一些简单的处理了,我顺便把我做的项目在github上的地址在下面放出,可供参考使用:
https://github.com/Phosphorus15/ExpectedVirus
- 关于javax.sound.midi包的一些浅层探究(三)
- 关于javax.sound.midi包的一些浅层探究(一)
- 关于javax.sound.midi包的一些浅层探究(二)
- Javax sound
- 关于Midi的疑问
- 关于标签的一些探究
- OSGI 中关于Module层包共享的一些注意事项
- 关于Javax.imageIO包的用法
- 关于javax.servlet包的配置
- 关于javax包找不到
- 关于实现HLS直播的一些探究
- 关于fork()函数特性的一些探究
- 关于无尽大师MxM的一些探究
- 关于正则一些探究
- 关于Windows下的MIDI基础编程
- AS3 sound类的一些技巧
- AS3 sound类的一些技巧
- 关于jar命令创建可运行包的小探究
- Xcode8升级后,必须注意的问题.
- 水仙花数算法浅析
- 直接拿来用,10个,9个PHP代码片段(不断更新~~)
- zookeeper集群搭建
- SwipeRefreshLayout与ListView,GridView,RecyclerView ,ScrollView 冲突问题总结
- 关于javax.sound.midi包的一些浅层探究(三)
- centos上的mavn的安装配置
- React 组件之间传值
- IntelliJ IDEA (idea)引入eclipse web项目
- leetcode-6-ZigZag Conversion
- day15 TreeSet
- Vsftp与PAM虚拟用户
- Android VideoView播放raw内视频
- 不同IE版本,引入不同的js文件。两种实现方式