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

Dependencies:   mbed SerialTxRxIntr DSP_MultirateLinearphase

main.cpp

Committer:
MikamiUitOpen
Date:
2022-03-30
Revision:
2:e97eaf13aa89
Parent:
1:c30bdcb9ba69

File content as of revision 2:e97eaf13aa89:

//----------------------------------------------------------------------
//  グラフィック・イコライザ,DA 出力はアップサンプリング使用
//      フィルタの係数は PC で計算し,それをマイコン側に転送するタイプ
//
//  PC 側のプログラム: F446_GraphicEqualizerB
//
//  2022/03/30, 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();     // 入力
    float yn = grEq_.Execute(xn);   // グラフィック・イコライザの処理
    myAdDa_.Output(yn);             // 出力
}

int main()
{
    SerialRxTxIntr rx(72);  // PC との通信用,バッファサイズ:72,9600 baud

    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]});
}