midiLibrary_add.m
资源名称:10_11.rar [点击查看]
上传用户:abcwxk
上传日期:2016-05-20
资源大小:434k
文件大小:4k
源码类别:
midi
开发平台:
Visual C++
- function notes_relative = midiLibrary_add();
- % 功能:1、调用Find_PPQN(file)函数,验证格式
- % 是否是单声道的midi format0,读取PPQN值
- % 2、读取所有的音符(包括静音段)的音高、
- % 通道、持续时间(即deltatime的值,时钟个数)
- % to be continued
- % 读取所有的Note On和Note Off消息
- % 事件的deltatime作为上一个事件的持续时间
- % 我们默认时间都是note on和note off交替进行
- % 如有几个音符同时发声的情况,第二个音符开始发声时
- % 认为前一个音符结束,再遇到它的note off消息时
- % 我们将会忽略,note on时间的delta time表示如果不为0
- % 认为是前面有静音的地方
- %
- % 知识点:参考 Borg.com+Midi+Specification.pdf Page158 : Events In an MTrk
- % Page 9 - 15 : Message, Note Off, Note On
- % 作者:刘涛 08年9月21日 22:07
- % 中国传媒大学 智能信息处理实验室
- % 0、打开文件
- [file,path]=uigetfile('*.mid','please select a midi file');
- filename=strcat(path,file);
- % 1、验证文件格式
- [tempo, time_signature, PPQN] = Find_PPQN(filename);
- % 2、将所有的音符信息保存成2 by n的notes矩阵
- % 从MTrk之后,找到T_quarterNote和mid_clock的长度
- % 保存mid中的音符
- fid = fopen(filename);
- if fid == -1
- error('打开文件失败');
- end
- % 读取MThd chunk 、mtrk头 和 长度
- temp = fread(fid,14+4+4, '*uint8');
- MTrk = temp(15:18);
- if sum(char(MTrk) == ['M'; 'T'; 'r'; 'k']) ~= 4
- error('不是MTrk头');
- end
- mtrkLength = double(temp(22)) + double(temp(21))*16^2 ...
- + double(temp(20))*16^4 + double(temp(19))*16^6;
- clear temp;
- % 全部读入MTrk chunk中的数据,以1个字节为单位循环分析数据
- % 检测note on状态位和note off状态位,并提取所有音符
- eventsData = fread(fid,mtrkLength,'*uint8');
- % 循环分析遍历event,保存其中的noteOn信息和noteOff信息,遇到非voice Message推出
- notes =eventsAnalyse(eventsData);
- % 统计notes中1/16 1/8 1/4等各种音符的个数
- notes_length = [];
- for i = 1:size(notes,1)
- if notes(i,1) == -1;
- continue;
- else
- notes_length = [notes_length notes(i,2)];
- end
- end
- notes_sta = [];
- for i = 1:size(notes_length,2)
- if isempty ( find(notes_sta == notes_length(i)) )
- notes_sta = [notes_sta; notes_length(i) 1];
- else
- n = find(notes_sta(:,1) == notes_length(i));
- notes_sta(n,2)= notes_sta(n,2) + 1;
- end
- end
- % 从最短音长的音符开始找,找到一个数量较多的最短音符最为quatize的基本单位
- sum_of_notes = sum(notes_sta(:,2));
- length_descend = sort(notes_sta(:,1));
- base_note_length = 0;
- for i = 1:length(length_descend)
- n = find(notes_sta(:,1) == length_descend(i));
- if notes_sta(n,2) / sum_of_notes > 0.2;
- base_note_length = length_descend(i);
- break;
- else
- continue;
- end
- end
- [m,n] = min(abs([PPQN PPQN/2 PPQN/4 PPQN/8] - base_note_length));
- base_note_length = PPQN / 2^(n-1);
- % 对音符量化
- rest_of_lastnote = 0;
- notes_quantize = [];
- for i = 1:size(notes)
- rest_of_notes = notes(i,2)-rest_of_lastnote
- N = round(rest_of_notes/ base_note_length )
- newnote = ones(1,N)*notes(i,1)
- notes_quantize = [notes_quantize newnote]
- rest_of_lastnote = rest_of_lastnote + base_note_length * N - notes(i,2)
- end
- % 将0音符的音高认为成是前一个音符的音高
- for i=1:length(notes_quantize)
- if notes_quantize(i) == -1;
- notes_quantize(i) = notes_quantize(i-1);
- end
- end
- % 转为相对音高序列
- notes_relative = notes_quantize(2:end) - notes_quantize(1:(size(notes_quantize,2)-1));
- % 把文件名和相对音高序列存入库中
- load midLib;
- count = midLib{1}+1;
- midData = midLib{1,2};
- midData{count,1} = file;
- midData{count,2} = notes_relative;
- newMidLib{1,1} = count;
- newMidLib{1,2} = midData;
- midLib = newMidLib;
- save midLib.mat midLib;
- return;