extract_pup_call_parameters.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. clear all
  2. close all
  3. rootpath='vpl_behav';
  4. bats = {'vpl_b2b3', 'vpl_b2b5', 'vpl_b2b8', 'vpl_b2mh', 'vpl_b3mt', ...
  5. 'vpl_b4b3', 'vpl_b4b5', 'vpl_b4b8', 'vpl_b4mb', 'vpl_b5mt', ...
  6. 'vpl_b7b3', 'vpl_b7b5', 'vpl_b7b8', 'vpl_b7my', 'vpl_b8mp'};
  7. % fixed variables
  8. fs=192e3;
  9. env_mad=0.005; % duration of the boxcar kernel(for moving average) to smooth envelope (s)
  10. env_flow=500;
  11. pk_thrs=-45; % dB
  12. pk_dist=0.02; % in seconds
  13. dur_thrs=-20; % dB
  14. freq_thrs=-20; % dB
  15. [hpb,hpa] = butter(8,2*50e3/fs,'high'); % 10 kHz high pass
  16. blockdur=60;
  17. mph=0.002;
  18. mpd=0.01*fs;
  19. nfft=128;
  20. for batnum=1:length(bats),
  21. filepath=[rootpath 'recordings\' bats{batnum} '\'];
  22. d=dir(filepath);
  23. wavnames=strvcat(d.name);
  24. for wavnum=3:size(wavnames,1);
  25. wavname=deblank(wavnames(wavnum,:));
  26. if 1-isempty(findstr(wavname,'m1.wav'));
  27. wavname
  28. cn=0;
  29. result=[];
  30. savname=[rootpath 'results\' bats{batnum} '\' wavname(1:end-4) '.mat'];
  31. fid=fopen(savname);
  32. if fid<0, % this file has not been analysed
  33. filesize=wavread([filepath wavname],'size');
  34. filename1=wavname(1:end-5);
  35. nblocks=ceil(filesize(1)/(blockdur*fs));
  36. for bn=1:nblocks,
  37. disp(['working on block ' num2str(bn) ' of ' num2str(nblocks)]);
  38. blockbuf=zeros(round(blockdur*fs),1);
  39. block_start=(bn-1)*round(blockdur*fs)+1;
  40. if bn < nblocks
  41. block_stop=bn*blockdur*fs;
  42. else
  43. block_stop=filesize(1);
  44. end
  45. blockbuf=zeros(block_stop-block_start+1,6);
  46. for micnum=1:6,
  47. micfile=[filename1 num2str(micnum) '.wav'];
  48. blockbuf(:,micnum)=wavread([filepath micfile],[block_start block_stop]);
  49. end
  50. compblockbuf=filtfilt(hpb,hpa,blockbuf);
  51. % call finder
  52. sumblockbuf=sum(abs(compblockbuf),2);
  53. % smooth the envelope
  54. [eb,ea]=butter(2,2*env_flow/fs);
  55. env_dB=20*log10(max(filtfilt(eb,ea,sumblockbuf),1e-4));
  56. %% find calls
  57. t=[0:length(env_dB)-1]/fs;
  58. % figure(2),
  59. % plot(env_dB)
  60. % hold on
  61. % xs=get(gca,'xlim');
  62. % ys=[pk_thrs pk_thrs];
  63. % lh=line(xs,ys);
  64. % set(lh,'color','r')
  65. [pk_val pk_pos]=findpeaks(env_dB,'minpeakheight',pk_thrs,'minpeakdistance',round(pk_dist*fs));
  66. if 1-isempty(pk_pos)
  67. % draw found peaks positions
  68. % hold on
  69. % plot(pk_pos,pk_val,'r*')
  70. % hold off
  71. % call cutting and saving
  72. for call_num=1:size(pk_pos)
  73. cn=cn+1;
  74. % determine start and stop of each call as -x dB duration
  75. env_dB=env_dB-env_dB(pk_pos(call_num));
  76. % find start of call
  77. start=max(find(env_dB(1:pk_pos(call_num))<dur_thrs));
  78. stop=min(find(env_dB(pk_pos(call_num):end)<dur_thrs))+pk_pos(call_num);
  79. if 1-isempty(stop) & 1-isempty(start)
  80. call_starts=(bn-1)*blockdur*fs+start;
  81. call_dur=(stop-start)/fs;
  82. result.call(cn).call_start_sample=call_starts;
  83. result.call(cn).call_dur=call_dur;
  84. call=blockbuf(start:stop,1:6);
  85. call_levels=20*log10(std(call));
  86. [call_level_max call_level_max_pos]=max(call_levels);
  87. xcall=call(:,call_level_max_pos);
  88. % figure(3)
  89. % subplot(2,1,1)
  90. % plot(xcall)
  91. % subplot(2,1,2)
  92. % spectrogram(xcall,nfft,120,nfft,fs,'yaxis');
  93. result.call(cn).call_levels=call_levels;
  94. result.call(cn).loudest_call=xcall;
  95. result_call(cn).loudest_mic=call_level_max_pos;
  96. %% --- call frequency parameter ----
  97. %% spectrogram method
  98. spects = pwelch(xcall,256,250,nfft,fs);
  99. spectsdB = 10*log10(spects);
  100. [ampl_pf pos_pf]= max(spectsdB);
  101. r = find(spectsdB >= ampl_pf+freq_thrs);
  102. faxis = (0:1/nfft:1/2).*fs;
  103. PF = faxis(pos_pf); % peak frequency
  104. Fmin = faxis(r(1)); % min frequency
  105. Fmax= faxis(r(end)); % max frequency
  106. BW= Fmax - Fmin; % bandwidth
  107. %% --- spectral centroid frequency
  108. SCF = sum(spects.*faxis')/sum(spects);
  109. SCF_dB = sum(spectsdB.*faxis')/sum(spectsdB);
  110. result.call(cn).PF=PF;
  111. result.call(cn).Fmin=Fmin;
  112. result.call(cn).Fmax=Fmax;
  113. result.call(cn).BW=BW;
  114. result.call(cn).SCF=SCF;
  115. result.call(cn).SCF_dB=SCF_dB;
  116. % use yin to calculate f0 as a function of time
  117. p.sr = fs;
  118. R=yin(xcall,p,0);
  119. f0s=R.f0;
  120. nframes=length(f0s);
  121. f0ts=(1:nframes)/(fs/R.hop);
  122. aperiodicity=R.ap0;
  123. % correct for f0 jumps
  124. fcin=[f0ts' f0s' aperiodicity'];
  125. fdiff=abs(diff(fcin(:,2)));
  126. finds=find(fdiff>9000);
  127. if 1-isempty(finds) % corrections are necessary
  128. f0_corrected=1;
  129. f0_corr=fcin(:,2);
  130. % check start frequency of the irregularity
  131. if f0_corr(finds(1))>30e3;
  132. % correct first jump
  133. f0_corr(1:finds(1))=f0_corr(1:finds(1))/2;
  134. if length(finds)>1,
  135. finds=finds(2:end);
  136. end
  137. end
  138. while length(finds)>1
  139. xfinds=finds(1:2);
  140. f0_corr(xfinds(1)+1:xfinds(2))=f0_corr(xfinds(1)+1:xfinds(2))/2;
  141. if length(finds)>2,
  142. finds=finds(3:end);
  143. elseif length(finds)==2,
  144. finds=[];
  145. break
  146. else
  147. break
  148. end
  149. end
  150. if length(finds)>0,
  151. f0_corr(finds(1)+1:end)=f0_corr(finds(1)+1:end)/2;
  152. end
  153. % figure(10), plot(fcin(:,1),fcin(:,2),'b',fcin(:,1),f0_corr,'r');
  154. %corr_ok=input('correction (1) ok or (0) not ok');
  155. corr_ok=1;
  156. if corr_ok==1,
  157. fcin(:,2)=f0_corr;
  158. end
  159. else
  160. f0_corrected=0;
  161. end
  162. result.call(cn).f0=fcin;
  163. result.call(cn).f0_corrected=f0_corrected;
  164. % fit f0(t)
  165. f0inds=find(1-isnan(fcin(:,2)));
  166. f0data=fcin(f0inds,1:2);
  167. [f0slope,sfm_amp,sfm_frq,sfm_phase]=fit_f0(f0data,0);
  168. result.call(cn).f0_slope=f0slope;
  169. result.call(cn).sfm_amp=sfm_amp;
  170. result.call(cn).sfm_frq=sfm_frq;
  171. result.call(cn).sfm_phase=sfm_phase;
  172. end
  173. end
  174. % pause;
  175. end
  176. drawnow;
  177. end
  178. save(savname,'result');
  179. else
  180. fclose(fid);
  181. end
  182. end
  183. end
  184. end