
Nucleo-F446 による残響生成器 . DA変換器にデータを送る際は 4 倍にアップ・サンプリング.
Dependencies: mbed SerialTxRxIntr F446_AD_DA_Multirate
Revision 0:8473107e47de, committed 2019-01-20
- Comitter:
- MikamiUitOpen
- Date:
- Sun Jan 20 10:46:15 2019 +0000
- Child:
- 1:47d242cf3d19
- Commit message:
- 1
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/F446_AD_DA_Multirate.lib Sun Jan 20 10:46:15 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/MikamiUitOpen/code/F446_AD_DA_Multirate/#9429fb179c38
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SerialTxRxIntr.lib Sun Jan 20 10:46:15 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/MikamiUitOpen/code/SerialTxRxIntr/#190d94fba10d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Jan 20 10:46:15 2019 +0000 @@ -0,0 +1,81 @@ +//---------------------------------------------------------------------- +// 残響発生器 +// 残響発生処理の有効/無効の切り替え:PC の "F446_AD_DA_OnOff.exe" +// +// 2019/01/20, Copyright (c) 2019 MIKAMI, Naoki +//---------------------------------------------------------------------- + +#include "F446_Multirate.hpp" +#include "reverb_unit.hpp" // 残響生成ユニット +#include "SerialRxTxIntr.hpp" +#pragma diag_suppress 870 // マルチバイト文字使用の警告抑制のため + +using namespace Mikami; + +int main() +{ + printf("\r\n残響生成器を開始します.\r\n"); + + SerialRxTxIntr rxTx; // Serial クラスの受送信割込み用オブジェクト + F446_Multirate myAdDa; // 出力標本化周波数を4倍にするオブジェクト + const int FS = 10000; // 入力の標本化周波数: 10 kHz + + const float G_C = 0.8f; + const float G_A = 0.6f; + const float G0 = 1.0f - G_C; + CombFilter<887> cm1(G_C); // 櫛形フィルタによる残響生成ユニット + CombFilter<1153> cm2(G_C); // 櫛形フィルタによる残響生成ユニット + CombFilter<1499> cm3(G_C); // 櫛形フィルタによる残響生成ユニット + AllpassFilter<97> ap1(G_A); // 全域通過フィルタによる残響生成ユニット + AllpassFilter<131> ap2(G_A); // 全域通過フィルタによる残響生成ユニット + + bool sw = true; // 残響生成有効/無効のスイッチ + + // F446_Multirate::Start() と F446_Multirate::Input() の間に + // printf() のように重い処理は実行しないこと. + myAdDa.Start(FS); // 標本化を開始する + + while (true) + { + //------------------------------------------------------------ + // ここにディジタルフィルタ等の処理を記述する + float xn = myAdDa.Input(); // 入力 + float xn2 = G0*xn; + + // 櫛形フィルタの並列接続部 + float yn = cm1.Execute(xn2) + cm2.Execute(xn2) + + cm3.Execute(xn2); + + // 全域通過フィルタの縦続接続部 + yn = ap2.Execute(ap1.Execute(yn)); + + // 入力信号(遅延なし)を加算 + yn = yn + xn2; + + if (sw) myAdDa.Output(yn); // 出力:残響付き + else myAdDa.Output(xn); // 出力:入力そのまま + //------------------------------------------------------------ + + //------------------------------------------------------------ + // PC からの指令に対応する処理 + if (rxTx.IsEol()) // 受信バッファのデータが有効になった場合の処理 + { + string str = rxTx.GetBuffer(); + if (str == "ENQ") + rxTx.Tx("ACK\n"); // PC からの "ENQ" に対して "ACK" を送信する + else // "ENQ" 以外の処理 + { + if (str == "ST") // PC から sw の状態の問い合わせ + { + if (sw) rxTx.Tx("EN"); // 残響発生器が有効であることを返信 + else rxTx.Tx("DS"); // 残響発生器が無効であることを返信 + } + if (str == "ON") sw = true; + if (str == "OFF") sw = false; + } + } + // PC からの指令に対応する処理はここまで + //------------------------------------------------------------ + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sun Jan 20 10:46:15 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/mbed/builds/3a7713b1edbc \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/reverb_unit.hpp Sun Jan 20 10:46:15 2019 +0000 @@ -0,0 +1,74 @@ +//-------------------------------------------------------------- +// 残響生成器で使うフィルタ +// +// 2018/07/11, Copyright (c) 2018 MIKAMI, Naoki +//-------------------------------------------------------------- + +#ifndef REVERB_UNIT_HPP +#define REVERB_UNIT_HPP + +#include "mbed.h" + +// 残響生成ユニットのための基底クラス +template<int delay> class Reverb +{ +private: + int ptr_; + float un_[delay]; // for delay +protected: + float Get() { return un_[ptr_]; } + void Set(float x) + { + un_[ptr_] = x; + if (++ptr_ >= delay) ptr_ = 0; + } +public: + // コンストラクタ + Reverb() : ptr_(0) { Clear(); } + + // 残響生成フィルタの実行(純粋仮想関数) + virtual float Execute(float x) = 0; + + // 内部遅延器のクリア + void Clear() + { for (int n=0; n<delay; n++) un_[n] = 0; } +}; + +// 櫛形フィルタによる残響生成ユニット +template<int delay> class CombFilter : public Reverb<delay> +{ +private: + const float GC_; +public: + // コンストラクタ + CombFilter(float g) : GC_(g) {} + + // 櫛形フィルタの実行 + virtual float Execute(float x) + { + float yn = Reverb<delay>::Get(); + Reverb<delay>::Set(x + GC_*yn); + return yn; + } +}; + +// 全域通過フィルタによる残響生成ユニット +template<int delay> class AllpassFilter : public Reverb<delay> +{ +private: + const float G0_; +public: + // コンストラクタ + AllpassFilter(float g) : G0_(g) {} + + // 全域通過フィルタの実行 + virtual float Execute(float x) + { + float un = x + G0_*Reverb<delay>::Get(); + float yn = -G0_*un + Reverb<delay>::Get(); + Reverb<delay>::Set(un); + return yn; + } +}; + +#endif // REVERB_UNIT_HPP