annotate aim-mat/tools/spectrogram.m @ 4:537f939baef0 tip

various bug fixes and changed copyright message
author Stefan Bleeck <bleeck@gmail.com>
date Tue, 16 Aug 2011 14:37:17 +0100
parents 20ada0af3d7d
children
rev   line source
tomwalters@0 1 % support file for 'aim-mat'
tomwalters@0 2 %
tomwalters@0 3 % This external file is included as part of the 'aim-mat' distribution package
bleeck@3 4 % (c) 2011, University of Southampton
bleeck@3 5 % Maintained by Stefan Bleeck (bleeck@gmail.com)
bleeck@3 6 % download of current version is on the soundsoftware site:
bleeck@3 7 % http://code.soundsoftware.ac.uk/projects/aimmat
bleeck@3 8 % documentation and everything is on http://www.acousticscale.org
bleeck@3 9
tomwalters@0 10
tomwalters@0 11 function f=spectrogram(sig,nr_f,maxfre)
tomwalters@0 12
tomwalters@0 13 nsig=changesr(sig,maxfre*2);
tomwalters@0 14 sr=getsr(nsig);
tomwalters@0 15 vals=getvalues(nsig);
tomwalters@0 16
tomwalters@0 17 % sig_len=getlength(sig);
tomwalters@0 18 % time_step=sig_len/nr_t;
tomwalters@0 19 % window=[0:time_step:sig_len];
tomwalters@0 20 % win_len=getnrpoints(nsig)/nr_t;
tomwalters@0 21 % window = hann(round(win_len));
tomwalters@0 22 % noverlap=round(win_len/2);
tomwalters@0 23 noverlap=nr_f*2-2;
tomwalters@0 24 [Bb,freqs,ts]=specgram(vals,nr_f*2,sr*2,[],noverlap);
tomwalters@0 25
tomwalters@0 26 B=Bb(2:nr_f+1,:);
tomwalters@0 27
tomwalters@0 28 nr_t=size(B,2);
tomwalters@0 29 nr_f=size(B,1);
tomwalters@0 30
tomwalters@0 31 srf=nr_t/getlength(sig);
tomwalters@0 32 f=field(nr_t,nr_f,srf);
tomwalters@0 33 f=setvalues(f,abs(B));
tomwalters@0 34 f=setmaxfre(f,maxfre);
tomwalters@0 35
tomwalters@0 36 return
tomwalters@0 37
tomwalters@0 38
tomwalters@0 39
tomwalters@0 40
tomwalters@0 41 % function f=spectrogram(sig,tstart,tstop,nr_t,nr_f,maxfre)
tomwalters@0 42 % alle Zeiten in Sekunden
tomwalters@0 43 % macht ein Sektrogramm aus dem Signal sig, das zu nr_t Zeiten gesampelt
tomwalters@0 44 % wird und nr_f Frequenzen hat
tomwalters@0 45 % das Signal wird aus sig in der Zeit von start bis stop genommen
tomwalters@0 46 % das Signal sig wird erst so auf eine Samplerate gebracht, dass
tomwalters@0 47 % das Resultat der FFT eine Auflösung bis maxfre hat.
tomwalters@0 48
tomwalters@0 49 if nargin<6
tomwalters@0 50 maxfre=GetSR(sig)/2;
tomwalters@0 51 end
tomwalters@0 52
tomwalters@0 53 % die alte (orginale) Samplerate
tomwalters@0 54 sr_old=GetSR(sig);
tomwalters@0 55
tomwalters@0 56 %wenn die maxfre anders ist als die, die das Signal mitbringt, dann muss das Signal heruntergesamplet werden:
tomwalters@0 57 if sr_old~=maxfre*2
tomwalters@0 58 sr_neu=maxfre*2;
tomwalters@0 59 sig=changesr(sig,sr_neu); % änder das ganze Signal zu der neuen SR
tomwalters@0 60 else
tomwalters@0 61 sr_neu=sr_old;
tomwalters@0 62 end
tomwalters@0 63
tomwalters@0 64 % Punkte, die die FFT benötigt, damit nr_f punkte hinten raus kommen
tomwalters@0 65 nr_fft=nr_f*2;
tomwalters@0 66 % und das ist ein Signal von dieser Länge: (auch mit neuer Samplerate)
tomwalters@0 67 stime=bin2time(nr_fft,sr_neu);
tomwalters@0 68 % Dauer des zu untersuchenden Signals
tomwalters@0 69 duration=tstop-tstart;
tomwalters@0 70 % wenn die gewünschte Samplingrate nicht hoch genug ist, weil zuviel Punkte erforderlich sind
tomwalters@0 71 if duration < stime
tomwalters@0 72 error('spectrogram: desired Samplingrate too low: take less points or higher freqeuncy!');
tomwalters@0 73 return;
tomwalters@0 74 end
tomwalters@0 75
tomwalters@0 76
tomwalters@0 77 % meine Notation ist anders als Matlab: Bei mir ist x die Zeit
tomwalters@0 78 % und y die Frequenz
tomwalters@0 79 sr_field=nr_t/duration; % die "SampleRate" des Feldes (sehr klein, da nur wenig Punkte)
tomwalters@0 80 f=field(nr_t,nr_f,sr_field);
tomwalters@0 81 f=setmaxfre(f,maxfre); % Für die Grafik: Wie hoch die Frequenzen geben
tomwalters@0 82
tomwalters@0 83 % damit die fft immer von einem richtigen vollen Signal gemacht werden kann, werden die
tomwalters@0 84 % FFTs an Stellen berechenet, die immer ein volles signal haben
tomwalters@0 85 time_step=(tstop-tstart-stime)/nr_t;
tomwalters@0 86
tomwalters@0 87 count=0;
tomwalters@0 88 w = hann(nr_fft); % for later: the window
tomwalters@0 89 % for t=56*time_step:time_step:tstop-stime-time_step
tomwalters@0 90
tomwalters@0 91 sig=setstarttime(sig,0);
tomwalters@0 92 for t=tstart:time_step:tstop-stime-time_step
tomwalters@0 93 count=count+1;
tomwalters@0 94 s1=t;
tomwalters@0 95 s2=t+stime;
tomwalters@0 96 if s2<tstop
tomwalters@0 97 s=getpart(sig,t,t+stime); % von diesem Teil soll die FFT gemacht werden
tomwalters@0 98 else % hier sollte er nicht hinkommen
tomwalters@0 99 s=getpart(sig,t,tstop);
tomwalters@0 100 s=expand(s,stime,0); % fülle den Rest mit Nullen auf, damit das Signal auf jeden Fall lang genug ist
tomwalters@0 101 end
tomwalters@0 102 s=setstarttime(s,0);
tomwalters@0 103 % damit die FFT nr_f Punkte hat, muss das Signal, womit sie gemacht wird, so lang sein:
tomwalters@0 104 % s2=changesr(s,sr_neu);
tomwalters@0 105 % ein HanningFenster drüberlegen:
tomwalters@0 106 s=s*w;
tomwalters@0 107 ps=powerspectrum(s,nr_f*2);
tomwalters@0 108 % the resultig powesprect is one point too large, because of the zerovalue->strip it
tomwalters@0 109 ps=strippowerspectrum(ps); % cut the leading zero
tomwalters@0 110 % figure(1)
tomwalters@0 111 % plot(s,'.-');
tomwalters@0 112 % figure(2)
tomwalters@0 113 % plot(ps,'.-');
tomwalters@0 114 % normiere das Spektrum auf die maximale Amplitude des Signals
tomwalters@0 115 ms=max(s);
tomwalters@0 116 ps=ps*ms;
tomwalters@0 117 f=setcolumn(f,count,ps);
tomwalters@0 118 end