Demo program of digital signal processing: Variable LPF/HPF, Vocal canceller, Pitch shifter, Reverbrator. ディジタル信号処理のデモプログラム. 遮断周波数可変 LPF/HPF,ボーカルキャンセラ,ピッチシフタ,残響生成器.

Dependencies:   Array_Matrix F446_AD_DA UIT_AQM1602 mbed

main.cpp

Committer:
MikamiUitOpen
Date:
2017-02-21
Revision:
6:96b4f6ce2dc9
Parent:
5:503bd366fd73

File content as of revision 6:96b4f6ce2dc9:

//--------------------------------------------------------
//  STM32F446 と信号処理用ボードによる信号処理のデモプログラム
//
//      SW: 偶数  入力をそのまま出力
//           1: 遮断周波数可変 LPF
//           3: 遮断周波数可変 HPF
//           5: ボーカルキャンセラ
//           7: ピッチシフタ
//           9: 残響生成器
//
//  2017/02/21, Copyright (c) 2017 MIKAMI, Naoki
//--------------------------------------------------------

#include "F446_ADC_Interrupt.hpp"   // AD, DA
#include "AQM1602.hpp"              // LCD 表示器
#include "MyFunctions.hpp"          // グローバル関数
#include "SignalProcessing.hpp"     // 信号処理の抽象基底クラスなど
#include "VariableLpHp.hpp"         // 遮断周波数可変フィルタ
#include "WeaverModulator.hpp"      // ピッチシフタ
#include "Reverbrator.hpp"          // 残響生成器用
using namespace Mikami;

const int FS_ = 24000;      // 標本化周波数: 24 kHz
AdcDual_Intr myAdc_(FS_);   // 参照:"F446_ADC_Interrupt.hpp"
DacDual myDac_;             // 参照:"F446_DAC.hpp"
DigitalOut ledG_(D10, 1);   // LED 緑色
BusIn sws_(D6, D7, D8, D9); // ロータリ・ディップ・スイッチ用
Ticker timer_;              // LED 点滅用

Through through_;               // そのまま出力
VariableLpHp filter_(10, FS_);  // 遮断周波数可変 IIR フィルタ
VocalCanceller vCancel_;        // ボーカルキャンセラ
FrqShifter fShifter_(FS_);      // ピッチシフタ
EchoSystem echo_;               // 残響生成器

// 割り込みが有効になる前にポインタに割り当てておく必要がある
SignalProcessing *spPtr_ = &through_;

void TimerIsr()
{
    static int count20 = 0;

    int sw = sws_.read();
    if ( ((sw & 0x01) == 0x01) && (sw < 10) )
    {
        if (count20 <= sw) ledG_ = !ledG_;
    }
    else
    {
        if (count20 < 10) ledG_ = 1;
        else              ledG_ = 0;
    }

    if (++count20 > 20)
    {
        count20 = 0;
        ledG_ = 0;
    }
}

// ADC 変換終了割り込みに対する割り込みサービス・ルーチン
void AdcIsr()
{
    float xn1, xn2, yn;
    myAdc_.Read(xn1, xn2);          // 入力
    yn = spPtr_->Execute(xn1, xn2); // sw の値に応じた信号処理の実行
    myDac_.Write(yn, yn);           // 出力
}

int main()
{
    printf("\r\nDemonstration for digital signal processing\r\n");

    sws_.mode(PullDown);

    AnalogIn a3In(A3);          // VR からの電圧読み取り用
    Aqm1602 lcd;                // LCD 表示器

    // 出力の LPF の遮断周波数を 10 kHz に設定
    myDac_.ScfClock(10000*100);

    NVIC_SetPriority(ADC_IRQn, 1);
    NVIC_SetPriority(TIM5_IRQn, 2); // Ticker の割り込み優先度を ADC より低くする


    timer_.attach(&TimerIsr, 0.2f); // タイマ割り込みの設定

    // ADC 変換終了割り込みに対する割り込みサービス・ルーチン割り当て
    myAdc_.SetIntrVec(&AdcIsr);

    int kind = -1;  // 処理の種類
    float frq;      // VR で設定された周波数

    while (true)
    {
        int sw;     // 現在の機能切り替えスイッチの状態
        do
        {
            sw = sws_.read();
            wait_ms(50);
        } while (sw != sws_.read());

        switch (sw)
        {
            case  1:    // 遮断周波数可変 LPF
                if (FrChange(a3In, 200, 2000, 10, frq) || (sw != kind))
                {
                    filter_.Design(frq, BilinearDesign::LPF);
                    AssignDisplay(filter_, lcd, "LPF", frq);
                }
                break;
            case  3:    // 遮断周波数可変 HPF
                if (FrChange(a3In, 200, 2000, 10, frq) || (sw != kind))
                {
                    filter_.Design(frq, BilinearDesign::HPF);
                    AssignDisplay(filter_, lcd, "HPF", frq);
                }
                break;
            case  5:    // ボーカルキャンセラ
                if (sw != kind)
                    AssignDisplay(vCancel_, lcd, "Vocal Calceller");
                break;
            case  7:    // ピッチシフタ
                if (FrChange(a3In, 0, 200, 1, frq) || (sw != kind))
                {
                    fShifter_.SetFrequensy(frq);
                    AssignDisplay(fShifter_, lcd, "Pitch Shifter", frq);
                }
                break;
            case  9:    // 残響生成器
                if (sw != kind)
                    AssignDisplay(echo_, lcd, "Reverbrator");
                break;                    
            default:
                if (sw != kind)
                    AssignDisplay(through_, lcd, "Through");
                break;                    
        }
        kind = sw;
        wait(0.2f);
    }
}