Realtime spectrum analyzer. Using FFT, linear prediction, or cepstrum smoothing. Version using MEMS microphone and CODEC, named "F746_RealtimeSpectrumAnalyzer_MEMS_Mic" is registered. リアルタイム スペクトル解析器.解析の手法:FFT,線形予測法,ケプストラムによる平滑化の3種類.このプログラムの説明は,CQ出版社のインターフェース誌,2016年4月号に掲載.外付けのマイクまたは他の信号源等を A0 に接続する.線形予測法,ケプストラムは,スペクトル解析の対象を音声信号に想定してパラメータを設定している.MEMS マイクと CODEC を使ったバージョンを "F746_RealtimeSpectrumAnalyzer_MEMS_Mic" として登録.

Dependencies:   BSP_DISCO_F746NG BUTTON_GROUP LCD_DISCO_F746NG TS_DISCO_F746NG UIT_FFT_Real mbed

MyClasses/LinearPrediction.cpp

Committer:
MikamiUitOpen
Date:
2016-02-22
Revision:
18:6630d61aeb3c
Parent:
4:99d4d5ea06a2

File content as of revision 18:6630d61aeb3c:

//-----------------------------------------------------
//  Class for linear prediction
//
//  2015/12/08, Copyright (c) 2015 MIKAMI, Naoki
//-----------------------------------------------------

#include "LinearPrediction.hpp"

namespace Mikami
{
    LinearPred::LinearPred(int nData, int order)
        : N_DATA_(nData), ORDER_(order),
          r_(new float[order+1]), k_(new float[order]),
          am_(new float[order]) {}

    LinearPred::~LinearPred()
    {
        delete[] r_;
        delete[] k_;
        delete[] am_;
    }

    // Calculate linear-predictive coefficients
    bool LinearPred::Execute(const float x[], float a[],
                             float &em)
    {
        AutoCorr(x);
        return Durbin(a, em);
    }

    // Calculate auto-correlation
    void LinearPred::AutoCorr(const float x[])
    {
        for (int j=0; j<=ORDER_; j++)
        {
            r_[j] = 0.0;
            for (int n=0; n<N_DATA_-j; n++)
                r_[j] = r_[j] + x[n]*x[n+j];
        }
    }

    // Levinson-Durbin algorithm
    bool LinearPred::Durbin(float a[], float &em)
    {
        // Initialization
        em = r_[0];

        // Repeat
        for (int m=0; m<ORDER_; m++)
        {
            float w = r_[m+1];
            for (int j=0; j<=m-1; j++)
                w = w - r_[m-j]*a[j];

            k_[m] = w/em;
            em = em*(1 - k_[m]*k_[m]);

            if (em < 0) break;  // Error for negative squared sum of residual

            a[m] = k_[m];
            for (int j=0; j<=m-1; j++)
                am_[j] = a[j];
            for (int j=0; j<=m-1; j++)
                a[j] = am_[j] - k_[m]*am_[m-j-1];
        }

        if (em < 0) return false;
        else        return true;
    }
}