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

Dependencies:   mbed SerialTxRxIntr DSP_MultirateLinearphase

Revision:
0:b3c94b253ae5
Child:
1:c30bdcb9ba69
--- /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]});
+}