ZCR_Noteseprate.m
上传用户:abcwxk
上传日期:2016-05-20
资源大小:434k
文件大小:4k
源码类别:

midi

开发平台:

Visual C++

  1. function notes_steps = ZCR_Noteseprate();
  2. % 打开文件
  3. clc;
  4. [filename,path]=uigetfile('*.wav','please select a wave file'); 
  5. filename=strcat(path,filename);
  6. [y,fs] = wavread(filename);
  7. % 可调参数
  8. sn = 30; % 过零率前加的白噪声的信噪比
  9. wn = 0.5; % 对有毛刺的过零率结果进行的低通滤波器的截止频率
  10. filterOnoff = 1; % 上述低通滤波器的开关
  11. factor = 1; % 对过零率结果进行门限判决,门限设为过零率的均值×factor
  12. % 音频做居中处理
  13. y =  y-sum(y)/length(y);
  14. % 加高斯白噪声
  15. yn = awgn(y, sn);
  16. % 特征提取,过零率、能量、频谱中心
  17. zcr = zeroCrossRate(yn, fs, 10, 10);
  18. % 浊音区间端点检测
  19. threshold = sum(zcr) / length(zcr) * factor; % 门限
  20. data = zcr - threshold;
  21. temp = [data 0].*[0 data];
  22. B = find( temp<0 );
  23. if data(B(1))>data(B(1)-1) % 判断第一个点是高zcr点还是低zcr点
  24.     % 高 第一个点要被舍弃,startpoints从第二点开始,endpoints从第三点开始
  25.     startpoints = B(2:2:end);
  26.     endpoints = B(3:2:end); % 认为第一个端点应该是清音或者静音的开始,后面的端点是清音与浊音交替
  27. else
  28.     % 低 第一个是低zcr点,startpoints从第一点开始,endpoints从第三点开始
  29.     startpoints = B(1:2:end); % 认为第一个端点应该是浊音段的开始,后面的端点是清音与浊音交替
  30.     endpoints = B(2:2:end);
  31. end
  32. % clear yn; clear zcr; clear zcrf; clear data; clear temp; clear B; clear A;
  33. % 除野点:持续时间小于100ms的浊音段,认为是野点,忽略掉
  34. voiceSoundSections = [];
  35. for i=1:length(startpoints)
  36.     if endpoints(i) - 1 - startpoints(i) < 10
  37.         continue;
  38.     else
  39.         voiceSoundSections = [voiceSoundSections [startpoints(i);endpoints(i)]];
  40.     end
  41. end
  42. startpoints = voiceSoundSections(1,:); 
  43. endpoints = voiceSoundSections(2,:)-1;
  44. %---------------
  45. figure;
  46. d=0.01;
  47. x=d:d:d*length(zcr);
  48. plot(x,zcr/max(zcr));
  49. hold on; plot(x,ones(1,length(zcr))*threshold/max(zcr)); title('过零率 & 端点切分结果');
  50. hold on; stem(d*startpoints,ones(1,length(startpoints)),'r');
  51. hold on; stem(d*endpoints,ones(1,length(endpoints)));
  52. %---------------
  53. % 求tempo
  54. tmp1 = startpoints(1:size(startpoints,2)-1);
  55. tmp2 = startpoints(2:end);
  56. tempo = min(tmp2-tmp1);
  57. tempo = min([tempo endpoints(end)-startpoints(end) ] )
  58. % 在每个tempo内,求一个平均绝对音高(Hz)
  59. % pitch = Pitch_Detection_Autocorrelation(y, fs, 30, 20);
  60. %  采用的是能量谱最大值的方法
  61. notes_frequence = [];
  62. samples_in_Frame = fs*10/1000;
  63. for i=2:length(startpoints)
  64.     N = round( (startpoints(i)-startpoints(i-1)) / tempo );
  65.     D=round((startpoints(i)-startpoints(i-1)) / N);
  66.     begin_sample = startpoints(i-1)*samples_in_Frame;
  67.     for j = 1:N
  68.         begin_sample = begin_sample + (j-1)*D*samples_in_Frame;
  69.         end_sample = begin_sample + D * samples_in_Frame -1;
  70.         data = y(begin_sample:end_sample);
  71.         spectral = abs(fft(data));
  72.         spectral = spectral(1:floor(length(spectral)/2) );
  73.         [tmp1,tmp2] = max(spectral);
  74.         fi = fs / length(data);
  75.         fmax = tmp2 * fi;        
  76.         notes_frequence = [notes_frequence fmax];
  77.     end
  78. end
  79. N = round((endpoints(end)-startpoints(end)) / tempo);
  80. D=(startpoints(i)-startpoints(i-1)) / N;
  81. begin_sample = startpoints(i-1)*samples_in_Frame;
  82. for j = 1:N
  83.     begin_sample = begin_sample + (j-1)*D*samples_in_Frame;
  84.     end_sample = begin_sample + D * samples_in_Frame -1;
  85.     data = y(begin_sample:end_sample);
  86.     spectral = abs(fft(data));
  87.     spectral = spectral(1:floor(length(spectral)/2) );
  88.     [tmp1,tmp2] = max(spectral);
  89.     fi = fs / length(data);
  90.     fmax = tmp2 * fi;        
  91.     notes_frequence = [notes_frequence fmax];
  92. end
  93. %  采用的是能量中心的方法,被放弃了
  94. % N = round((endpoints(end)-startpoints(end)) / tempo);
  95. % D=(startpoints(i)-startpoints(i-1)) / N;
  96. % begin_sample = startpoints(i-1)*samples_in_Frame;
  97. % for j = 1:N
  98. %     begin_sample = begin_sample + (j-1)*D*samples_in_Frame;
  99. %     end_sample = begin_sample + D * samples_in_Frame -1;
  100. %     data = y(begin_sample:end_sample);
  101. %     spectral = abs(fft(data));
  102. %     spectral = spectral(1:floor(length(spectral)/2) );
  103. %     E= sum(spectral.^2);
  104. %     if(sum(spectral)==0)
  105. %         centroid = 0;
  106. %     else
  107. %         centroid = sum(spectral.^2.*(1:length(spectral))') / E * 1000 / 20;
  108. %     end
  109. %     notes_frequence = [notes_frequence centroid];
  110. % end
  111. % 转换成相对音高(音阶)
  112. notes_steps = zeros(1,length(notes_frequence)-1);
  113. for i = 2 : length(notes_frequence)
  114.     current_pitch = notes_frequence(i);
  115.     previous_pitch = notes_frequence(i-1);
  116.     notes_steps(i-1) = round(12*(log(current_pitch)-log(previous_pitch))/log(2));
  117. end
  118. disp('输入音频的相对音高结果:')
  119. return;