CQエレクトロニクス・セミナで使用するグラフィック・イコライザ のプログラム

Dependencies:   mbed SerialTxRxIntr DSP_MultirateLinearphase

Files at this revision

API Documentation at this revision

Comitter:
MikamiUitOpen
Date:
Fri Feb 25 02:18:16 2022 +0000
Child:
1:c30bdcb9ba69
Commit message:
1

Changed in this revision

DSP_MultirateLinearphase.lib Show annotated file Show diff for this revision Revisions of this file
GraphicEqualizer/BiquadGrEq.hpp Show annotated file Show diff for this revision Revisions of this file
GraphicEqualizer/GraphicEqualizer.cpp Show annotated file Show diff for this revision Revisions of this file
GraphicEqualizer/GraphicEqualizer.hpp Show annotated file Show diff for this revision Revisions of this file
SerialTxRxIntr.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DSP_MultirateLinearphase.lib	Fri Feb 25 02:18:16 2022 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/MikamiUitOpen/code/DSP_MultirateLinearphase/#f7bfe38c93ab
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GraphicEqualizer/BiquadGrEq.hpp	Fri Feb 25 02:18:16 2022 +0000
@@ -0,0 +1,50 @@
+//--------------------------------------------------------------
+//  グラフィックイコライザで使う 1D タイプの 2 次のフィルタ
+//      このクラスでは,係数は実行中に書き換えられることを想定している
+//
+//      v[n] = x[n] + a1*v[n-1] + a2*v[n-2]
+//      y[n] = b0*v[n] + b1*v[n-1] + b2*v[n-2]
+//          x[n] :  入力信号
+//          y[n] :  出力信号
+//
+//  2022/02/18, Copyright (c) 2022 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#include "mbed.h"
+
+#ifndef IIR_BIQUAD_GREQ_HPP
+#define IIR_BIQUAD_GREQ_HPP
+
+// 2 次の IIR フィルタ
+namespace Mikami
+{
+    class BiquadGrEq
+    {
+    public:
+        struct Coefs { float a1, a2, b0, b1, b2; };
+
+        BiquadGrEq(const Coefs ck = (Coefs){0, 0, 0, 0, 0})
+            : c_(ck), vn1_(0), vn2_(0) {}
+        
+        void SetCoefficients(const Coefs ck) { c_ = ck; }
+
+        float Execute(float xn)
+        {
+            float vn = xn + c_.a1*vn1_ + c_.a2*vn2_;
+            float yn = c_.b0*vn + c_.b1*vn1_ + c_.b2*vn2_;
+        
+            vn2_ = vn1_;
+            vn1_ = vn;
+
+            return yn;
+        }
+
+    private:
+        Coefs c_;
+        float vn1_, vn2_;
+
+        // コピー・コンストラクタ禁止
+        BiquadGrEq(const BiquadGrEq&);
+    };
+}
+#endif  // IIR_BIQUAD_GREQ_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GraphicEqualizer/GraphicEqualizer.cpp	Fri Feb 25 02:18:16 2022 +0000
@@ -0,0 +1,30 @@
+//--------------------------------------------------------------
+//  グラフィックイコライザのクラス
+//      フィルらの係数を設定しない場合は,出力は出ない
+//
+//  2022/02/19, Copyright (c) 2022 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#include "GraphicEqualizer.hpp"
+
+namespace Mikami
+{
+    // コンストラクタ
+    GrEqualizer::GrEqualizer(int bands, float fs, float qVal)
+        : BANDS_(bands), Q_VAL_(qVal),
+          biquad_(bands), f0_(bands)
+    {
+        for (int n=0; n<BANDS_; n++) f0_[n] = 62.5f*powf(2, n);
+        SetOff();
+        Validate();
+    }
+
+    // グラフィック・イコライザの実行
+    float GrEqualizer::Filtering(float xn)
+    {
+        float yn = xn;
+        for (int n=0; n<BANDS_; n++)
+            yn = biquad_[n].Execute(yn);
+        return yn;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GraphicEqualizer/GraphicEqualizer.hpp	Fri Feb 25 02:18:16 2022 +0000
@@ -0,0 +1,57 @@
+//--------------------------------------------------------------
+//  グラフィックイコライザのクラス(ヘッダ)
+//      フィルらの係数を設定しない場合は,出力は出ない
+//
+//  2022/02/19, Copyright (c) 2022 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#include "Array.hpp"
+#include "BiquadGrEq.hpp"
+
+#ifndef GRAPHIC_EQALIZER_HPP
+#define GRAPHIC_EQALIZER_HPP
+
+namespace Mikami
+{
+    class GrEqualizer
+    {
+    public:
+        // コンストラクタ
+        GrEqualizer(int bands, float fs, float qVal = 1.0f/sqrtf(2.0f));
+        // グラフィック・イコライザの実行
+        float Execute(float xn) { return (this->*fPtr_)((this->*fPtr2_)(xn)); }
+        
+        // 指定したチャンネルの係数を設定する
+        void SetCoefficients(int band, BiquadGrEq::Coefs coefs)
+        { biquad_[band].SetCoefficients(coefs); }
+
+        // グラフィック・イコライザの処理を有効にする
+        void Validate() { fPtr_ = &GrEqualizer::Filtering; }
+        // グラフィック・イコライザの処理を無効にする
+        void Invalidate() { fPtr_ = &GrEqualizer::Through; }
+        // 出力を On にする    
+        void SetOn() { fPtr2_ = &GrEqualizer::On; }
+        // 出力を Off にする
+        void SetOff() { fPtr2_ = &GrEqualizer::Off; }
+
+    private:
+        const int BANDS_;       // バンドの数
+        const float Q_VAL_;     // Q 値
+
+        Array<BiquadGrEq> biquad_;
+        Array<float> f0_;
+
+        float (GrEqualizer::*fPtr_)(float);     // イコライザ処理の有無
+        float (GrEqualizer::*fPtr2_)(float);    // 出力の On/Off
+        
+        float Through(float xn) { return xn; }  // そのまま出力
+        float Filtering(float xn);              // フィルタを実行して出力
+        float On(float xn) { return xn; }       // 出力: On
+        float Off(float xn) { return 0; }       // 出力: Off
+
+        // コピー・コンストラクタ,代入演算子禁止禁止のため
+        GrEqualizer(const GrEqualizer&);
+        GrEqualizer& operator=(const GrEqualizer&);
+    };
+}
+#endif  // GRAPHIC_EQALIZER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialTxRxIntr.lib	Fri Feb 25 02:18:16 2022 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/MikamiUitOpen/code/SerialTxRxIntr/#268977533f95
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Feb 25 02:18:16 2022 +0000
@@ -0,0 +1,79 @@
+//----------------------------------------------------------------------
+//  グラフィック・イコライザ,DA 出力はアップサンプリング使用
+//      フィルタの係数の計算をマイコン側でも行うタイプ
+//
+//  PC 側のプログラム: F446_GraphicEqualizerB
+//
+//  2022/02/19, Copyright (c) 2022 MIKAMI, Naoki
+//----------------------------------------------------------------------
+
+#include "MultirateLiPh.hpp"    // DA でアップサンプリング
+#include "SerialRxTxIntr.hpp"
+#include "GraphicEqualizer.hpp"
+#include <cctype>           // isalpha(), isdigit() で使用
+using namespace Mikami;
+
+const float FS_ = 44.1f;    // 入力の標本化周波数: 44.1 kHz
+MultirateLiPh myAdDa_(FS_); // 出力標本化周波数を4倍にするオブジェクト
+
+const int BANDS_ = 9;       // グラフィック・イコライザのバンド数
+GrEqualizer grEq_(BANDS_, FS_*1000);    // グラフィック・イコライザ用オブジェクト
+
+void Select(string str);        // 有効,無効,平坦化,出力 On/Off に対応する処理の選択
+void NumericCtrl(string str);   // 帯域ごとの利得調整
+
+// グラフィック・イコライザの信号処理
+void AdcIsr()
+{
+    float xn = myAdDa_.Input()*0.25f;   // 入力
+    float yn = grEq_.Execute(xn);       // グラフィック・イコライザの処理
+    myAdDa_.Output(yn);                 // 出力
+}
+
+int main()
+{
+    SerialRxTxIntr rx(72);  // PC との通信用,9600 baud,バッファサイズ:72
+
+    NVIC_SetPriority(ADC_IRQn, 0);  // AD変換終了割り込みの優先度が最高
+    NVIC_SetPriority(USART2_IRQn, 1);
+
+    myAdDa_.Start(&AdcIsr); // 標本化を開始する
+    while (true)
+    {
+        if (rx.IsEol())     // PC からの指令に対応する処理
+        {
+            string str = rx.GetBuffer();
+            if (str == "GrEqB") rx.TxString("ACK\n");        // "ACK" を送り返す
+            else
+            {
+                if (isalpha(str[0])) Select(str);
+                if (isdigit(str[0])) NumericCtrl(str);
+                // 第1文字がアルファベットでも数字でもない場合は何もしない
+            }
+        }
+    }
+}
+
+// 有効,無効,平坦化,出力 On/Off に対応する処理の選択
+void Select(string str)
+{
+    if (str == "ACTIVE")  grEq_.Validate();     // フィルタ処理有効
+    if (str == "THROUGH") grEq_.Invalidate();   // フィルタ処理無効
+    if (str == "ON")      grEq_.SetOn();        // 出力を On
+    if (str == "OFF")     grEq_.SetOff();       // 出力を Off
+}
+
+// 帯域ごとの利得調整
+void NumericCtrl(string str)
+{
+    // 最初の2文字はフィルタの番号
+    int band = atoi(str.substr(0, 2).c_str());  // フィルタの番号
+    // 次の文字からは係数の値
+    const int N = 5;    // 係数の個数
+    const int L0 = 13;  // 一つの係数に対する文字数
+    float c[N];
+    for (int n=0; n<N; n++)
+        c[n] = atof(str.substr(n*L0+2, L0).c_str());
+    grEq_.SetCoefficients(band,
+                          (BiquadGrEq::Coefs){c[0], c[1], c[2], c[3], c[4]});
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Feb 25 02:18:16 2022 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400
\ No newline at end of file