//--------------------------------------------------------------
//	正弦波標本化波形の描画，補間の有無の効果
//		補間点を表示するように修正した
//		0 次ホールドの状態を表示するように修正した
//
//		作成者：三上直樹，2023/01/30 作成，ⓒ三上直樹 2023
//--------------------------------------------------------------

using System;
using System.Windows.Forms;

using Mikami;
using Mikami.Filter;
using Mikami.WindowsApplication;

using static System.Math;

namespace 正弦波_補間有無
{
	public partial class Form1 : Form
	{
		private const int N_START_ = 300;
		private const int N_USE_ = 150;
		private const int N_DATA_ = N_START_ + N_USE_ + 40000/100;
		private const int OVS_ = 4;				// オーバーサンプリング比

		private const float X_MIN_ = 100.0f;	// 周波数の最小値
		private const float X_MAX_ = 4300.0f;	// 周波数の最大値
		private const float FS_ = 10000.0f;		// 標本化周波数 = 10 kHz
		// tFactor_: 周波数と TrackBar のツマミの位置の関係を表す係数
		private readonly double tFactor_ = Log10(X_MAX_/X_MIN_)/(X_MAX_ - X_MIN_);

		private readonly float dpiFactor_;		// 異なる DPI システム用スケール変換係数
		private readonly RadioGroup scaleH_;	// 横倍率の情報を保持

		private float[] xn_ = new float[N_DATA_];	// 標本化した信号に対応する配列
		
		public Form1()
		{
			InitializeComponent();

			// 異なる DPI のシステムに対応するスケール変換の係数を取得
			dpiFactor_ = CreateGraphics().DpiX/96.0f;

			trackBar1.Minimum = (int)X_MIN_;	// TrackBar の最小値を設定
			trackBar1.Maximum = (int)X_MAX_;	// TrackBar の最大値を設定

			trackBar1_Scroll(null, null);		// パラメータが初期状態の場合の波形の表示

			numericUpDown1.Maximum = (decimal)X_MAX_;
			numericUpDown1.Minimum = (decimal)X_MIN_;
			numericUpDown1.Value = numericUpDown1.Minimum;

			scaleH_ = new RadioGroup(groupBox1);

			FormCloseConfirm.Set(this);			// 終了時に確認できるようにする
		}

		// 終了
		private void button1_Click(object sender, EventArgs e)
		{
			Close();
		}

		// 入力の正弦波の周波数を trackBar1 で設定し，正弦波を発生させる
		private void trackBar1_Scroll(object sender, EventArgs e)
		{
			int iFrq = (int)Round(X_MIN_*Pow(10, tFactor_*(trackBar1.Value - X_MIN_)));
			numericUpDown1.Value = iFrq;
		}

		// 周波数を numericUpDown1 で設定する
		private void numericUpDown1_ValueChanged(object sender, EventArgs e)
		{
			double frq = (double)numericUpDown1.Value;
			trackBar1.Value = (int)(X_MIN_ + Round(Log10(frq/X_MIN_)/tFactor_));
			label4.Text = (frq < 1000) ? frq.ToString() + " Hz"
							: (frq/1000.0).ToString("#.000") + " kHz";

			SineGen(frq);

			pictureBox1.Invalidate();
			pictureBox2.Invalidate();
		}

		// numericUpDown1 の入力文字列を全選択の状態にする
		private void numericUpDown1_Click(object sender, EventArgs e)
		{
			numericUpDown1.Select(0, numericUpDown1.Value.ToString().Length);
		}

		// numericUpDown1 で Enter キー入力時の Beep 音を消す
		private void numericUpDown1_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Enter) e.SuppressKeyPress = true;
		}

		// 出力波形の倍率（振幅）の設定，描画の方法の変更の指令
		private void radioButton1_Click(object sender, EventArgs e)
		{
			pictureBox1.Invalidate();
			pictureBox2.Invalidate();
		}

		// 補間点描画のあり／なしの切替え
		private void radioButton8_CheckedChanged(object sender, EventArgs e)
		{
			pictureBox2.Invalidate();
		}

		// 0 次ホールドのあり／なしの切替え
		private void radioButton10_CheckedChanged(object sender, EventArgs e)
		{
			if (radioButton11.Checked)
			{
				radioButton7.Enabled = false;
				radioButton6.Checked = true;
			}
			else
				radioButton7.Enabled = true;
			pictureBox1.Invalidate();
			pictureBox2.Invalidate();
		}

		// 補間する前の波形の描画指令
		private void pictureBox1_Paint(object sender, PaintEventArgs e)
		{
			DrawWaveform(e.Graphics, xn_, N_START_, 1);
		}

		// 補間した波形の描画指令
		private void pictureBox2_Paint(object sender, PaintEventArgs e)
		{
			float[] y = new float[xn_.Length];
			xn_.CopyTo(y, 0);
			float[] ym = Interpolator.Execute(y, N_DATA_);	// 帯域制限補間
			DrawWaveform(e.Graphics, ym, N_START_*OVS_+Interpolator.ORDER_/2, OVS_);
		}

		// 入力正弦波の周波数の目盛描画
		private void pictureBox3_Paint(object sender, PaintEventArgs e)
		{
			DrawTickValue.Execute(e.Graphics, this, X_MAX_/X_MIN_);
		}
	}
}
