といっても、PCの中の発振器です。 振幅変調された複素信号の検波にシミュレーションを行うために、まずは、複素信号発生器を作成しました。
タイマーを使って、連続的に発生しています。 サンプリング周波数が低いので、高い周波数ではきれいな正弦波にはなりません。
”実数のみ”のチェックボックスは、複素信号ではなく実信号だけになります。 ”反転は、実部と虚部を入れ替えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
using System; using System.Collections.Generic; using System.Windows.Forms; using System.Numerics; namespace AM_Detector { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private DrawGraph dg; private oscilltor osc; private Queue<Complex[]> sig_data; private const int datapoint = 1024; private const int sample_rate = 44100; private void button1_Click(object sender, EventArgs e) { timer1.Start(); } private void button2_Click(object sender, EventArgs e) { timer1.Stop(); } private void checkBox1_CheckedChanged(object sender, EventArgs e) { if (checkBox1.Checked == true) { checkBox2.Checked = false; checkBox2.Enabled = false; } else { checkBox2.Enabled = true; } } private void trackBar1_Scroll(object sender, EventArgs e) { label2.Text = (trackBar1.Value / 10.0).ToString(); } private void Form1_Load(object sender, EventArgs e) { dg = new DrawGraph(pictureBox1); osc = new oscilltor(8000, sample_rate, false, false); sig_data = new Queue<Complex[]>(); label2.Text = (trackBar1.Value / 10).ToString(); } private void pictureBox1_Paint(object sender, PaintEventArgs e) { dg.DrawAxis(e.Graphics); if (sig_data.Count > 0) dg.DrawData(e.Graphics, sig_data.Dequeue()); } private void timer1_Tick(object sender, EventArgs e) { Complex[] data = new Complex[datapoint]; if (checkBox1.Checked) osc.real = true; else osc.real = false; if (checkBox2.Checked) osc.swap = true; else osc.swap = false; osc.frequency = trackBar1.Value * 100; for (int i = 0; i < datapoint; i++) data[i] = osc.tick(); sig_data.Enqueue(data); pictureBox1.Refresh(); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
using System; using System.Numerics; namespace AM_Detector { class oscilltor { private double _frequency; private int _sample_rate; private bool _real; private bool _swap; private double sin_value; private double cos_value; private Complex osc_vect; public oscilltor(double freq, int sample_rate, bool real, bool swap) { _frequency = freq; _sample_rate = sample_rate; _real = real; _swap = swap; update(); osc_vect = new Complex(0, 1); } public double frequency { get { return _frequency; } set { _frequency = value; update(); } } public int sample_rate { get { return _sample_rate; } set { _sample_rate = value; update(); } } public bool real { get { return _real; } set { _real = value; } } public bool swap { get { return _swap; } set { _swap = value; } } private void update() { var anglepertikc = 2.0 * Math.PI * _frequency / _sample_rate; sin_value = Math.Sin(anglepertikc); cos_value = Math.Cos(anglepertikc); } public Complex tick() { Complex vect; vect = (osc_vect.Real * cos_value - osc_vect.Imaginary * sin_value) + Complex.ImaginaryOne * (osc_vect.Imaginary * cos_value + osc_vect.Real * sin_value); osc_vect = vect; if (real) vect = vect.Real + vect.Real*Complex.ImaginaryOne; else if (swap) vect = vect.Imaginary + Complex.ImaginaryOne * vect.Real; return vect; } public void reset_angle() { osc_vect = Complex.ImaginaryOne; } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
using System.Drawing; using System.Windows.Forms; using System.Numerics; namespace AM_Detector { class DrawGraph { private PictureBox picturebox_; private float x0_; //x軸原点 private float y0_; //y軸原点 private float y1_; //y軸1に対するピクセル値 private float width_; private Font myfont_ = new Font("MS UI Gothic", 10); private SolidBrush mysolidbrush_ = new SolidBrush(Color.Black); private const float x_offset = 10.0F; private const float y_offset = 10.0F; //コンストラクタ public DrawGraph(PictureBox myPictureBox) { picturebox_ = myPictureBox; x0_ = picturebox_.Left; y0_ = picturebox_.ClientSize.Height - 1; y1_ = y0_ /(float)(1.2* 32000); width_ = picturebox_.ClientSize.Width - 1; } public void DrawAxis(Graphics gr) { DrawVerticalLines(gr, Pens.Black); DrawHolizontalLines(gr, Pens.Black); } private void DrawHolizontalLines(Graphics gr, Pen mypen) { float yn = y0_ / 10; for (int i = 0; i <= y0_; i += 1) gr.DrawLine(mypen, 0, y0_ - yn * i, width_, y0_ - yn * i); } private void DrawVerticalLines(Graphics gr, Pen mypen) { float xn = width_ / 10; for (int i = 0; i <= (int)width_; i += 1) gr.DrawLine(mypen, xn * i, 0, xn * i, y0_); } public void DrawData(Graphics gr, Complex[] gdata) { Pen mypen = new Pen(Color.Red); for(int i=0; i<gdata.Length; i++) gdata[i] = 10000.0 * gdata[i]; PointF ioldPoint = new PointF(0, (float)(y0_ + y1_ * gdata[0].Real - y0_/2)); PointF qoldPoint = new PointF(0, (float)(y0_ + y1_ * gdata[0].Imaginary - y0_ / 2)); float tick = width_ / gdata.Length*40; for (int i = 1; i < gdata.Length - 1; i++) { mypen.Color = Color.Red; PointF inewPoint = new PointF(i * tick, (float)(y0_ + y1_ * gdata[i].Real-y0_/2)); gr.DrawLine(mypen, ioldPoint, inewPoint); ioldPoint = inewPoint; mypen.Color = Color.Green; PointF qnewPoint = new PointF(i * tick, (float)(y0_ + y1_ * gdata[i].Imaginary - y0_ / 2)); gr.DrawLine(mypen, qoldPoint, qnewPoint); qoldPoint = qnewPoint; } } } } |