eventsAnalyse.m
资源名称:10_11.rar [点击查看]
上传用户:abcwxk
上传日期:2016-05-20
资源大小:434k
文件大小:6k
源码类别:
midi
开发平台:
Visual C++
- % ------------------------------------------------------------------------------------------------
- function notes =eventsAnalyse(eventsData)
- % description
- % 分析events数据,找出noteOn和noteOff事件,notes存储音符的时长和音高
- % 从内存中的eventsData中,分析events
- % 分析文件中第一个noteon开始的所有events,只分析voice message
- % 遇到system message和meta-data message会退出
- % 方法:
- % 1、找到第一个note on的status byte,将data1存储到notes(1,1)中,notes(1,2)=0
- % 2、循环分析events
- % (1)delta time: 调用[value, len] = readViaLen(via)给函数传入下面4个字节的数据
- % 获得变长量的value和data长度,数据指针指向下一个delta time
- % (2)status byte :
- % >0 得到状态字节: 如果是running
- % status,则状态=lastStatus,指针指向data bytes
- % >1 通过映射表找到对应于status byte的data-bytes的长度
- % 利用长度判断非voice msg情况,将error退出
- % >2 voice msg
- % <1 存储status 到 lastStatus
- % <2 是note on或者note off,将音高和音长存入notes中
- % >3 从data-bytes的长度得到下一个delta-time的开始位置,
- % 若到结尾退出,改变数据指针位置,循环
- % (3)data bytes:无
- % Note:
- % 遇到除了voice message之外的会提示出错
- % 08.9.22 21:27
- % 0、初始化一些变量
- % 1) Status Byte Of Voice Messages
- noteOn = 9*16; noteOff = 8*16; afterTouch = 10*16;
- controlChange = 11*16; programChange = 12*16;
- channelPressure = 13*16; pitchWheel = 14*16;
- system_exclusive = 240;
- meta_data = 255; tempo_meta = 81;
- time_meta = 88;
- noteNum = 0; % 音符号
- numOfNotes = 0; % 音符个数
- noteSound = 1; noteMute = 0; noteState = noteMute; % 音符类别,无声音符 & 有声音符
- bytePointer = 1; % 指针在eventsData中的位置
- % 王方师哥qq教我的映射表方法
- v_msg_dataBytesLength = zeros(256,1);
- v_msg_dataBytesLength(noteOn) = 2;
- v_msg_dataBytesLength(noteOff) = 2;
- v_msg_dataBytesLength(afterTouch) = 2;
- v_msg_dataBytesLength(controlChange) = 2;
- v_msg_dataBytesLength(programChange) = 1;
- v_msg_dataBytesLength(channelPressure) = 1;
- v_msg_dataBytesLength(pitchWheel) = 2;
- % 小方 21:04:27% 就是一个数组
- % 小方 21:05:03% 比如说下标是status-byte,对应定内容是date-bytes长度
- % 漓江烟雨 21:05:15% 哦
- % 漓江烟雨 21:05:16% 呵呵
- % 小方 21:05:28% 这样直接通过[]访问就行了
- % 2) 找到Tempo, Time Signature, PPQN / SMPTE
- % 放在里find_PPQN函数中
- % 1、找到第一个note on message
- n = length(eventsData);
- m=0; % 第一个noteOn message的status byte位置
- for i = 1 : n-2
- state = bitand(eventsData(i), 240); % 0xF0 240
- if(state == noteOn)
- if eventsData(i+2)==0
- continue; % 力度为0情况,表示note off情况
- else
- m = i;
- break;
- end
- end
- end
- % if m==0; % 没有找到音符情况
- % return;
- % end
- noteNum = double(eventsData(m+1));
- notes = [noteNum 0];
- numOfNotes = 1;
- % if m+3 >n % 到结尾了
- % return;
- % end
- noteState = noteSound;
- lastStatus = noteOn;
- bytePointer = m+3;
- % 2、逐个分析events,保存其中的noteOn和Off信息到notes
- for i = bytePointer : n
- if i==1290
- i;
- end
- if i ~= bytePointer
- continue;
- end
- % a delta time:
- % 调用[value, len] = readViaLen(via)给函数传入下面4个字节的数据
- % 获得变长量的value和data长度,数据指针指向下一个status byte
- via = eventsData(i:i+3);
- [value, len] = readViaLen(via)
- i=i+len;
- % b status byte :
- % b.0 得到状态字节: 检测running status,则状态=lastStatus,指针指向databytes
- if bitand(128, eventsData(i)) ~= 0 % 0x80 128
- % 不是 running status
- status = bitand(eventsData(i), 240); % 0xF0 240
- i=i+1; % 指针指向databytes
- else
- status = lastStatus;
- i=i; % 指针指向databytes
- end
- if status == meta_data;
- disp('error! 是Meta-data');
- return;
- elseif status > system_exclusive
- disp('error! 是system-exclusive Message');
- return;
- end
- % b.1 通过映射表找到对应于status byte的data-bytes的长度
- % 利用长度判断非voice msg情况,将error退出
- dataBytesLength = v_msg_dataBytesLength(status);
- if dataBytesLength==0
- disp('error! 不是Voice Message');
- return;
- end
- % b.2 voice msg
- % b.2.1 存储status 到 lastStatus
- lastStatus = status;
- % b.2.2 是note on或者note off,将音高和音长存入notes中
- if status == noteOn && eventsData(i+1) ~= 0 % note On情况
- if noteState == noteSound
- % 保存前一个音符
- deltatime = value;
- notes(numOfNotes, 2) = value;
- % 增加一个有声音符
- noteNum = double(eventsData(i));
- notes = [ notes; [noteNum 0] ];
- numOfNotes = numOfNotes + 1;
- % 状态
- noteState == noteSound;
- elseif noteState == noteMute
- % 保存前一个音符
- deltatime = value;
- if value ~= 0 % 即前一个noteOff事件的持续时间不是0,是一个无声音符,需要保存
- notes(numOfNotes, 2) = value;
- % 增加一个有声音符
- noteNum = double(eventsData(i));
- notes = [ notes; [noteNum 0] ];
- numOfNotes = numOfNotes + 1; % 音符数+1
- else % 前一个noteOff时间的持续时间是0,不是无声音符
- % 将前面定义的无声音符去掉,改成有声音符
- noteNum = eventsData(i);
- notes(numOfNotes, 1) = noteNum;
- numOfNotes = numOfNotes; % 音符数不变
- end
- % 状态
- noteState = noteSound;
- end
- elseif status == noteOff | (status == noteOn && eventsData(i+1) == 0) % note Off情况
- % 保存前一个音符
- deltatime = value;
- notes(numOfNotes, 2) = value;
- % 增加一个无声音符
- notes = [ notes; [-1 0] ];
- numOfNotes = numOfNotes + 1;
- % 状态
- noteState = noteMute;
- else
- disp('其他的voice msg');
- end
- % b.2.3 其他voice msg不管,从data-bytes的长度得到下一个delta-time的开始位置,
- % 若到结尾退出,改变数据指针位置,循环
- i = i+dataBytesLength;
- if i >n
- return;
- end
- bytePointer = i;
- end
- return;