//-------------------------------------------------------------
//	アンダーサンプリングのデモ
//
//	作成者：三上直樹，2023/01/28 作成，ⓒ三上直樹 2023
//-------------------------------------------------------------
using System;
using System.Windows.Forms;

using Mikami.Filter;
using Mikami.WindowsApplication;

using static System.Math;

namespace アンダーサンプリング
{
	public partial class Form1 : Form
	{
		private const double FS_ =  10.0e3;		// 標本化周波数： 10 kHz
		private const double RATE_ = 10;		// 標本化周波数に対するアナログ信号描画の周波数比
		private const double FSA_ = FS_*RATE_;	// アナログ信号描画の標本化周波数
		private const double TSA_ = 1.0/FSA_;	// アナログ信号描画の標本化間隔
		private const double PI2_ = 2*PI;
		private const int DATA_N_ = 2000;		// データ数
		private const int DATA_D_ = 200;		// 表示するサンプル数

		private const float DT_ = 1.6f;			// アナログ信号描画の間隔（10μs 相当）
		private const float Y_UNIT_ = -20.0f;
		private const int START_ = 400;			// 表示する際の最初の点
		private const int DY0_ = 120;

		private double[] vA_ = new double[DATA_N_];	// アナログ信号
		private double[] vD_ = new double[DATA_N_];	// 離散的信号
		private double[] vR_ = new double[DATA_N_];	// 再生されたアナログ信号

		private readonly InterpolationFir lpf_;
		private readonly InterpolationFir bpf1_;
		private readonly InterpolationFir bpf2_;

		private readonly RadioGroup frq_;
		private readonly RadioGroup band_;

		private double f1_ = 2000;		// 2 kHz
		private double f2_;

		public Form1()
		{
			InitializeComponent();

			lpf_ = new InterpolationFir(hkLpf_, RATE_);
			bpf1_ = new InterpolationFir(hkBpf1_, RATE_);
			bpf2_ = new InterpolationFir(hkBpf2_, RATE_);
			Generate();
			Reconstruct(lpf_);

			frq_ = new RadioGroup(groupBox1, s => s.Replace(" kHz", ""));
			band_ = new RadioGroup(groupBox2, s => s.Replace(" kHz", ""));
		}

		private void Form1_Paint(object sender, PaintEventArgs e)
		{
			Drawing(e.Graphics);
		}

		private void radioButton1_Click(object sender, EventArgs e)
		{
			f2_ = 0;
			if (!frq_.Checked.Contains("+"))
				f1_ = int.Parse(frq_.Checked)*1000;
			else
			{
				var str = frq_.Checked.Trim(" ".ToCharArray())
									  .Split("+".ToCharArray());
				f1_ = int.Parse(str[0])*1000;
				f2_ = int.Parse(str[1])*1000;
			}
			Generate();
			SelectReconstructor();
		}

		private void radioButton5_Click(object sender, EventArgs e)
		{
			SelectReconstructor();
		}

		private void Generate()
		{
			// 元のアナログ信号
			double pi2f1 = PI2_*f1_;
			double pi2f2 = PI2_*f2_;
			for (int n=0; n<DATA_N_; n++)
				vA_[n] = Cos(pi2f1*TSA_*n) + 0.8*Sin(pi2f2*TSA_*n);

			// 標本化された信号
			for (int n=0; n<DATA_N_; n++) vD_[n] = 0;
			for (int n=0; n<DATA_N_; n+=10) vD_[n] = vA_[n];
		}

		// アナログ信号の再生
		private void Reconstruct(InterpolationFir filter)
		{
			for (int n=0; n<DATA_N_; n++) vR_[n] = filter.Execute(vD_[n]);
		}

		private void SelectReconstructor()
		{
			switch (band_.Checked)
			{
				case "0－5"   : Reconstruct(lpf_); break;	// LPF
				case "5－10"  : Reconstruct(bpf1_); break;	// BPF1
				case "10－15" : Reconstruct(bpf2_); break;	// BPF2
			}
			Invalidate();
		}
	}
}
