【问题标题】:How does Octave spectrogram 'specgram' from signal work?信号中的八度频谱图“频谱图”如何工作?
【发布时间】:2012-08-30 13:17:05
【问题描述】:

我正在尝试测试位于 Octave 信号包中的 specgram 函数,但我对 specgram 的输入/输出变量有点困惑。我想做的是能够将频谱图数据放入一个数组中,该数组将显示频率以及频率开始和停止时的时间长度。

参见下面的示例代码:我试图让数组显示 t1 的长度为 7hz,t2 为 12hz,t3 为 2hz。我该怎么做?

我使用的是 ubuntu 12.04 和 octave 3.2.4 以及信号包 1.0.11

% combines sig with spectra plot
clear all,clc,tic;
fs=1000;
t1=linspace(0,2*pi,fs/0.1); %need to round off no decimals
t2=linspace(0,2*pi,fs/0.3); %need to round off no decimals
t3=linspace(0,2*pi,fs/0.6); %need to round off no decimals

%Create signal in different arrays
y1=sin(7*t1);
y2=sin(12*t2);
y3=sin(2*t3);

%append arrays to test specgram
yt = [y1 y2 y3];

%plot(yt) %will show combined plot

%Spectrum section
yts=specgram(yt',20,500, 2,1);
plot(yts)
fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);

【问题讨论】:

标签: matlab fft octave spectrogram


【解决方案1】:

这里有一些示例代码可以做到这一点。比有人告诉您升级软件并阅读说明要好得多。

fs = 100;
t = 0:1/fs:10;
x = [sin(2*pi*7*t), sin(2*pi*12*t), sin(2*pi*2*t)];
specgram(x,256,1000, [],200);

【讨论】:

    【解决方案2】:

    你说你用的是 Octave 3.2.4,现在最新的是 3.6.2,明显过时了。 ftp://ftp.gnu.org/gnu/octave/

    你说你用的是1.0.11的信号包,最新的是1.1.3,有点过时了。 http://octave.sourceforge.net/signal/index.html

    每当处理函数无法正常工作的原因时,请始终获取最新最好的版本。

    您是否阅读过有关信号包函数 specgram 的官方 octave 文档?

    http://octave.sourceforge.net/signal/function/specgram.html

    在你这样做之后,你是否为 specgram 运行了一些演示?它们对你有用吗?

    http://octave.sourceforge.net/signal/function/specgram.html

    以下是八度音阶谱图的来源,它包含有关其工作原理的 cmets。它可能会阐明如何正确使用它:

    ## Copyright (C) 2000 Paul Kienzle
    ##
    ## This program is free software and may be used for any purpose.  This
    ## copyright notice must be maintained. Paul Kienzle is not responsible
    ## for the consequences of using this software.
    ## usage: [S, f, t] = spectrogram(x, Fs, window, step, maxF, shape, minE)
    ##
    ## Generate a spectrogram for the signal. This chops the signal into
    ## overlapping slices, windows each slice and applies a Fourier
    ## transform to determine the frequency components at that slice. 
    ##
    ## x:      signal to analyse
    ## Fs:     sampling rate for the signal
    ## window: analysis window length (default 30 msec)
    ## step:   time between windows, start to start (default 5 ms)
    ## maxF:   maximum frequency to display (default 4000 Hz)
    ##    Alternatively, use [maxF, nF], where nF is the minimum
    ##    of frequency points to display.  If nF is greater than
    ##    what it would normally be for the given window size and
    ##    maximum displayed frequency, the FFT is zero-padded until
    ##    it at least nF points are displayed on the y axis.
    ## shape:  window analysis function (default 'hanning')
    ##    Shape is any function which takes an integer n and returns
    ##    a vector of length n.  If shape contains %d and ends with
    ##    ')', as for example '(1:%d)' or 'kaiser(%d,0.5)' do, then 
    ##    %d is replaced with the desired window length, and the
    ##    expression is evaluated.
    ## minE:   noise floor (default -40dB)
    ##    Any value less than the noise floor is clipped before the
    ##    spectrogram is displayed.  This limits the dynamic range
    ##    that your spectrogram must accomodate.  Alternatively,
    ##    use [minE, maxE], where maxE is the clipping ceiling, also
    ##    in decibels.
    ##
    ## Return values
    ##    S is the spectrogram in S with linear magnitude normalized to 1.
    ##    f is the frequency indices corresponding to the rows of S.
    ##    t is the time indices corresponding to the columns of S.
    ##    If no return value is requested, the spectrogram is displayed instead.
    ##
    ## Global variables
    ##    spectrogram_{window,step,maxF,nF,shape,minE,maxE} can override
    ##    the default values with your own.
    ##
    ## To make a good spectrogram, generating spectral slices is only half
    ## the problem.  Before you generate them, you must first choose your
    ## window size, step size and FFT size.  A wide window shows more
    ## harmonic detail, a narrow window shows more formant structure.  This
    ## defines your time-frequency resolution. Step size controls the
    ## horizontal scale of the spectrogram. Decrease it to stretch, or
    ## increase it to compress. Certainly, increasing step size will reduce
    ## time resolution, but decreasing it will not improve it much beyond
    ## the limits imposed by the window size (you do gain a little bit,
    ## depending on the shape of your window, as the peak of the window
    ## slides over peaks in the signal energy).  The range 1-5 msec is good
    ## for speech. Finally, FFT length controls the vertical scale, with
    ## larger values stretching the frequency range.  Clearly, padding with
    ## zeros does not add any information to the spectrum, but it is a
    ## cheap, easy and good way to interpolate between frequency points, and
    ## can make for prettier spectrograms.
    ##
    ## After you have generated the spectral slices, there are a number of
    ## decisions for displaying them.  Firstly, the entire frequency range
    ## does not need to be displayed.  The frequency range of the FFT is
    ## determined by sampling rate.  If most of your signal is below 4 kHz
    ## (in speech for example), there is no reason to display up to the
    ## Nyquist frequency of 10 kHz for a 20 kHz sampling rate.  Next, there
    ## is the dynamic range of the signal.  Since the information in speech
    ## is well above the noise floor, it makes sense to eliminate any
    ## dynamic range at the bottom end.  This is done by taking the max of
    ## the normalized magnitude and some lower limit such as -40 dB.
    ## Similarly, there is not much information in the very top of the
    ## range, so clipping to -3 dB makes sense there. Finally, there is the
    ## choice of colormap.  A brightness varying colormap such as copper or
    ## bone gives good shape to the ridges and valleys.  A hue varying
    ## colormap such as jet or hsv gives an indication of the steepness of
    ## the slopes.
    
    ## TODO: Accept vector of frequencies at which to sample the signal.
    ## TODO: Consider accepting maxF (values > 0), shape (value is string)
    ## TODO:    and dynamic range (values <= 0) in any order.
    ## TODO: Consider defaulting step and maxF so that the spectrogram is
    ## TODO:    an appropriate size for the screen (eg, 600x100).
    ## TODO: Consider drawing in frequency/time grid; 
    ## TODO:    (necessary with automatic sizing as suggested above)
    ## TODO: Consider using step vs. [nT, nF] rather than maxF vs [maxF, nF]
    ## TODO: Figure out why exist() is so slow: 50 ms vs 1 ms for lookup. 
    
    function [S_r, f_r, t_r] = spectrogram(x, Fs, window, step, maxF, shape, minE)
    global spectrogram_window=30;
    global spectrogram_step=5;
    global spectrogram_maxF=4000;
    global spectrogram_shape="hanning";
    global spectrogram_minE=-40;
    global spectrogram_maxE=0;
    global spectrogram_nF=[];
    
    if nargin < 2 || nargin > 7
        usage ("[S, f, t] = spectrogram(x, fs, window, step, maxF, shape, minE)");
    end
    
    if nargin<3 || isempty(window), 
        window=spectrogram_window; 
    endif
    if nargin<4 || isempty(step), 
        step=spectrogram_step; 
    endif
    if nargin<5 || isempty(maxF), 
        maxF=spectrogram_maxF; 
    endif
    if nargin<6 || isempty(shape), 
        shape=spectrogram_shape;
    endif
    if nargin<7 || isempty(minE), 
        minE=spectrogram_minE; 
    endif
    if any(minE>0)
        error ("spectrogram clipping range must use values less than 0 dB");
    endif
    if length(minE)>1,
        maxE=minE(2); 
        minE=minE(1); 
    else
        maxE = spectrogram_maxE;
    endif
    if length(maxF)>1,
        min_nF=maxF(2);
        maxF=maxF(1);
    else
        min_nF=spectrogram_nF;
    endif
    
    ## make sure x is a column vector
    if size(x,2) != 1 && size(x,1) != 1
        error ("spectrogram data must be a vector");
    end
    if size(x,2) != 1, x = x'; end
    
    if (maxF>Fs/2)
        ## warning("spectrogram: cannot display frequencies greater than Fs/2");
        maxF = Fs/2;
    endif
    
    step_n = fix(step*Fs/1000);    # one spectral slice every step ms
    
    ## generate window from duration and shape function name
    win_n = fix(window*Fs/1000);
    if shape(length(shape)) == ')' 
        shape = sprintf(shape, win_n);
    else
        shape = sprintf("%s(%d)", shape, win_n);
    endif
    win_vec = eval(strcat(shape,";"));
    if size(win_vec,2) != 1, win_vec = win_vec'; endif
    if size(win_vec,2) != 1 || size(win_vec,1) != win_n,
        error("spectrogram %s did not return a window of length %d", \
            shape, win_n);
    endif
    
    ## FFT length from size of window and number of freq. pts requested
    fft_n = 2^nextpow2(win_n);    # next highest power of 2
    dF = Fs/fft_n;                # freq. step with current fft_n
    nF = ceil(maxF(1)/dF);        # freq. pts with current fft_n,maxF
    if !isempty(min_nF)           # make sure there are at least n freq. pts
        if min_nF > nF,             # if not enough
        dF = maxF/min_nF;            # figure out what freq. step we need
        fft_n = 2^nextpow2(Fs/dF);   # figure out what fft_n this requires
        dF = Fs/fft_n;               # freq. step with new fft_n
        nF = ceil(maxF/dF);          # freq. pts with new fft_n,maxF
        endif
    endif
    
    ## build matrix of windowed data slices
    offset = 1:step_n:length(x)-win_n;
    S = zeros (fft_n, length(offset));
    for i=1:length(offset)
        S(1:win_n, i) = x(offset(i):offset(i)+win_n-1) .* win_vec;
    endfor
    
    ## compute fourier transform
    S = fft (S);
    S = abs(S(1:nF,:));        # select the desired frequencies
    S = S/max(S(:));           # normalize magnitude so that max is 0 dB.
    S = max(S, 10^(minE/10));  # clip below minF dB.
    S = min(S, 10^(maxE/10));  # clip above maxF dB.
    
    f = [0:nF-1]*Fs/fft_n;
    t = offset/Fs;
    if nargout==0
        imagesc(f,t,20*log10(flipud(S)));
    else
        S_r = S;
        f_r = f;
        t_r = t;
    endif
    
    endfunction
    

    谱图输入:

    usage: [S [, f [, t]]] = specgram(x [, n [, Fs [, window [, overlap]]]]) 
    
    x: vector of samples
    
    n: size of fourier transform window, or [] for default=256
    
    Fs: sample rate, or [] for default=2 Hz
    
     window:shape of the fourier transform window, or [] for default=hanning(n)
    
     Note:window length can be specified instead, in which case window=hanning(length)
    
     overlap:overlap with previous window, or [] for default=length(window)/2
    

    谱图输出:

    S is 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.
    

    【讨论】:

      【解决方案3】:

      从源代码在 Fedora Linux 中安装 specgram 的演练。

      如果您想真正了解 Specgram 的工作原理。您必须从源代码安装它,以便在它运行时在引擎盖下四处寻找。我在 64 位 Fedora 17 机器上演示了这一点。我假设您有一个名为el 的用户。我之前安装了 3.6.3,发现 specgram 需要 3.8.0。所以在这个演练中是一个升级的例子。

      新建目录/home/el/foo3,启动octave命令行并测试:

      el@defiant ~/foo3 $ octave
      octave:4> [5,5]
      ans =
      
         5   5
      

      在 /home/el/foo3 下使用此代码创建一个名为 wegetsignal.m 的新文件并运行它:

      startfreq=200;
      fs=44100;
      endfreq=20;
      dursec= 10;%duration of signal in seconds
      t=(0:dursec*fs)/fs; %Time vector
      alpha=log(startfreq/endfreq)/dursec;
      sig = exp(-j*2*pi*startfreq/alpha*exp(-alpha*t));
      sig=(sig/max(abs(sig))*.8); %normalize signal
      specgram(sig,150,400);
      

      运行它:

      el@defiant ~/foo3 $ octave wegetsignal.m
      GNU Octave, version 3.6.3
      warning: X11 DISPLAY environment variable not set
      error: `specgram' undefined near line 9 column 1
      error: called from:
      error:   /home/el/foo3/w.m at line 9, column 1
      

      您收到此错误是因为您尚未安装信号包。

      下载信号包:

      从这里获取信号 1.3.0.tar.gz:http://octave.sourceforge.net/signal/index.html

      el@defiant ~/foo3 $ wget -O signal-1.3.0.tar.gz http://sourceforge.net/projects/octave/files/Octave%20Forge%20Packages/Individual%20Package%20Releases/signal-1.3.0.tar.gz/download?use_mirror=softlayer-dal&download=
      
      el@defiant ~/foo3 $ ls
      signal-1.3.0.tar.gz  wegetsignal.m
      
      el@defiant ~/foo3 $ octave
      octave:1> pkg install signal-1.3.0.tar.gz
      error: the following dependencies where unsatisfied:
         signal needs octave >= 3.8.0
       signal needs control >= 2.4.5
       signal needs general >= 1.3.2
      

      好的,所以我有 octave 3.6.3,它说我们至少需要 3.8.0 让我们这样做。

      删除我的旧版本 octave:

      sudo yum remove octave
      Removed:
        octave.x86_64 6:3.6.3-2.fc17
      

      从源代码下载最新最好的 Octave 3.8.0

      以下是我使用的步骤,可能对你有所不同

      wget ftp://ftp.gnu.org/gnu/octave/octave-3.8.0.tar.bz2
      tar -xvf octave-3.8.0.tar.bz2
      cd octave-3.8.0
      

      我需要一些额外的包,我必须一起破解,如果你还没有安装它们,你可能需要这些:

      yum install gcc-gfortran
      yum-builddep octave
      yum install lapack lapack-devel blas blas-devel
      

      配置制作和安装

      ./configure
      make
      sudo make install
      

      测试一下,打印一个矩阵

      octave:1> [5, 5]
      ans =
      
         5   5
      

      现在安装包specgram

      el@defiant ~/foo3 $ octave
      octave:1> pkg install signal-1.3.0.tar.gz
      error: the following dependencies were unsatisfied:
         signal needs control >= 2.4.5
       signal needs general >= 1.3.2
      

      我们需要控制和通用

      在此处查找:http://octave.sourceforge.net/packages.php 并安装:

      el@defiant ~/foo3 $ wget -O control-2.6.2.tar.gz "http://downloads.sourceforge.net/project/octave/Octave%20Forge%20Packages/Individual%20Package%20Releases/control-2.6.2.tar.gz?r=http%3A%2F%2Foctave.sourceforge.net%2Fpackages.php&ts=1393090607&use_mirror=hivelocity"
      
      el@defiant ~/foo3 $ wget -O general-1.3.4.tar.gz "http://downloads.sourceforge.net/project/octave/Octave%20Forge%20Packages/Individual%20Package%20Releases/general-1.3.4.tar.gz?r=http%3A%2F%2Foctave.sourceforge.net%2Fpackages.php&ts=1393090783&use_mirror=softlayer-dal"
      
      el@defiant ~/foo3 $ ls
      control-2.6.2.tar.gz  octave-3.8.0          signal-1.3.0.tar.gz
      general-1.3.4.tar.gz  octave-3.8.0.tar.bz2  wegetsignal.m
      

      您必须将文件移动到 octave 可以读取它们的位置:

      sudo cp general-1.3.4.tar.gz /usr/local/share/octave/packages/
      sudo cp control-2.6.2.tar.gz /usr/local/share/octave/packages/
      sudo cp signal-1.3.0.tar.gz /usr/local/share/octave/packages/
      

      然后您必须从 octave 交互式 shell 安装它(以 root 身份):

      [root@defiant foo3]# octave --no-gui
      
      octave:1> pkg install control
      octave:1> pkg install general
      octave:1> pkg install signal
      

      他们最多需要 2 分钟才能完成。

      然后你必须在终端上加载它们。

      el@defiant ~/foo3 $ octave
      octave:1> pkg load signal
      octave:2> wegetsignal
      doneoctave:3> 
      

      它有效:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-03-25
        • 2017-09-08
        • 1970-01-01
        • 1970-01-01
        • 2022-12-01
        • 1970-01-01
        • 2015-06-12
        • 2019-11-09
        相关资源
        最近更新 更多