summaryrefslogtreecommitdiff
path: root/macros/specgram.sci
blob: e1ca6dce1dca83867a3561e3f284fd2d1e03c2d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright (C) 2018 - IIT Bombay - FOSSEE
//
// This file must be used under the terms of the CeCILL.
// This source file is licensed as described in the file COPYING, which
// you should have received as part of this distribution.  The terms
// are also available at
// http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
// Author:[insert name]
// Organization: FOSSEE, IIT Bombay
// Email: toolbox@scilab.in



function [S_r, f_r, t_r] = specgram(x, n , Fs , win , overlap)
//Generate a spectrogram for the signal x. The signal is chopped into overlapping segments of length n, and each segment is windowed and transformed into the frequency domain using the FFT. The default segment size is 256. If fs is given, it specifies the sampling rate of the input signal. The argument window specifies an alternate window to apply rather than the default of hanning (n). The argument overlap specifies the number of samples overlap between successive segments of the input signal. The default overlap is length (window)/2.

//CALLING SEQUENCE:
//[S, f, t] = specgram (x,n,fs,window,overlap)
//where
//S is the complex output of the FFT, one row per slice
//f is the frequency indices corresponding to the rows of S
// t is the time indices corresponding to the columns of S.



//Test cases:
//////1.
//N=1024;
//n=0:N-1;
//w=2*%pi/5;
//x=sin(w*n)+10*sin(2*w*n);
//[s,f,t]=specgram(x);
//grayplot(f,t,s)
//xlabel("frequency")
//ylabel("time")
////
[nargout,nargin]=argn();
  if nargin < 1 | nargin > 5
    error("wrong no. of input arguments");
  // make sure x is a vector
  elseif size(x,"c") ~= 1 & size(x,"r") ~= 1
    error ("specgram data must be a vector");
  end

  if nargin==1 then
      n=min(256,length(x));
      Fs=2;
      win = window("hn",n);
      overlap=ceil(length(win)/2);
      end




  if size(x,"c") ~= 1
       x = x';
        end

  // if only the win length is given, generate hanning win
  if isscalar(win)
       win = window("hn",win);

        end

  // should be extended to accept a vector of frequencies at which to
  // evaluate the Fourier transform (via filterbank or chirp
  // z-transform)
  if ~isscalar(n)
    error("specgram doesnot handle frequency vectors yet");
  end

  if (length (x) <= length (win))
    error ("specgram: segment length must be less than the size of X");
  end

  // compute win offsets
  win_size = length(win);
  if (win_size > n)
    n = win_size;
    warning ("specgram fft size adjusted to %d", n);
  end
  step = win_size - overlap;

  // build matrix of wined data slices
  offset = [ 1 : step : length(x)-win_size ];
  S = zeros (n, length(offset));
  for i=1:length(offset)
    S(:, i) =( x(offset(i):offset(i)+win_size-1).* win');
  end

  // compute Fourier transform
  S = fft (S);

  // extract the positive frequency components
  if (n-fix(n/2)*2)==1
    ret_n = (n+1)/2;
  else
    ret_n = n/2;
  end
  S = S(1:ret_n, :);

  f = [0:ret_n-1]*Fs/n;
  t = offset/Fs;
//  if nargout==0
//    //Matplot(20*log10(abs(S)));
//    //set (gca (), "ydir", "normal");
//    xlabel ("Time")
//    ylabel ("Frequency")
//  end
  if nargout>0
       S_r = S;
       end
  if nargout>1
       f_r = f;
        end
  if nargout>2
       t_r = t;
        end

endfunction