サンプリングと復元
#include <GL/freeglut.h> #define _USE_MATH_DEFINES #define _CRT_SECURE_NO_WARNINGS #include <math.h> #include <stdio.h> #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 #define X_WIDTH 700 #define Y_HEIGHT 100 void disp0(int f[], int x0Position, int y0position, int amplitude); void disps(int fs[], int x0Position, int y0position, int amplitude); void dispr(int fr[], int x0Position, int y0position, int amplitude, int k); void Line2D(int x1, int y1, int x2, int y2, float size) { glLineWidth(size); glBegin(GL_LINES); glVertex2i(x1, y1); glVertex2i(x2, y2); glEnd(); } void display(void) { int f[X_WIDTH]; //原波形の値をX_WIDTH秒分記憶する.1秒間隔 int fs[X_WIDTH]; //サンプリング波形の値をX_WIDTH秒分記憶する.1秒間隔 int fsh[X_WIDTH]; //サンプルホールド波形の値をX_WIDTH秒分記憶する.1秒間隔 int fr[X_WIDTH]; //復元波形の値をX_WIDTH秒分記憶する.1秒間隔 int tidePeriod = 50;//原波形の周期[s] int samplingInterval = 5;//サンプリング間隔[s] int samplingStartMargin = 0;//0[s]からサンプリング開始までの待ち時間[s] int decodingWidth = 3;//復元するときに参照する範囲 int ns; int amplitude; int x0Position, y0position; int i, j; char input[255]; //パラメータ設定(ここから) //ここで値を変えて,波形の変化を確認する. tidePeriod = 40;//原波形の周期[s] samplingInterval = 2;//サンプリング間隔[s] samplingStartMargin = 0;//0[s]からサンプリング開始までの待ち時間[s] decodingWidth = 3;//復元するときに参照する範囲 //パラメータ設定(ここまで) ns = X_WIDTH / (double)samplingInterval + 0.5;//サンプル数 x0Position = 50; amplitude = 30; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //原波形------------------------------------------------------------------------- for (i = 0; i < X_WIDTH; i++) { f[i] = amplitude*sin(2.0*M_PI*(double)i / (double)tidePeriod); } y0position = 70; disp0(f, x0Position, y0position, amplitude); //サンプリング波形表示------------------------------------------------------------------------- for (j = 0; j < X_WIDTH; j++) { if ((j-samplingStartMargin)% samplingInterval == 0) { fs[j] = f[j]; } else { fs[j] = 0 ; } } y0position += 100; //disps(fs, x0Position, y0position, amplitude, ts, ns); disps(fs, x0Position, y0position, amplitude); //サンプルホールド------------------------------------------------------------------------- int preValue = 0;//ホールドする値を記憶するための変数 for (i = 0; i < X_WIDTH; i++) { if (fs[i] == 0) { fsh[i] = preValue; } else { fsh[i] = fs[i]; preValue = fs[i]; } } y0position += 100; disp0(fsh, x0Position, y0position, amplitude); //復元 int k = decodingWidth; for (j = 0; j < X_WIDTH; j++) { int sum = 0; for (i = j - k; i <= j + k; i++) { if(0 <= i && i <= X_WIDTH) sum += fsh[i]; } fr[j] = sum / (double)(2 * k + 1); } y0position += 100; dispr(fr, x0Position, y0position, amplitude, k); glFlush(); } void Init() { glClearColor(0.0, 0.0, 0.0, 1.0); glOrtho(0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, -1, 1); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitWindowPosition(100, 100); glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); glutInitDisplayMode(GLUT_RGBA); glutCreateWindow("波形描画"); glutDisplayFunc(display); Init(); glutMainLoop(); return 0; } void disp0(int f[], int x0Position, int y0position, int amplitude) { int i; glColor4f(1.0f, 1.0f, 1.0f, 1.0f); //X軸,Y軸描画 Line2D(x0Position, y0position - amplitude, x0Position, y0position + amplitude, 1.0); Line2D(x0Position, y0position, x0Position + X_WIDTH, y0position, 1.0); glLineWidth(1); glBegin(GL_POINTS); glColor4f(0.0f, 1.0f, 0.0f, 1.0f); glVertex2i(x0Position, y0position - f[0]); for (i = 1; i < X_WIDTH; i++) { glVertex2i(x0Position + i, y0position - f[i]); } glEnd(); } void disps(int fs[], int x0Position, int y0position, int amplitude) { int i; glColor4f(1.0f, 1.0f, 1.0f, 1.0f); //X軸,Y軸描画 Line2D(x0Position, y0position - amplitude, x0Position, y0position + amplitude, 1.0); Line2D(x0Position, y0position, x0Position + X_WIDTH, y0position, 1.0); glLineWidth(1); glBegin(GL_LINES); glColor4f(0.0f, 1.0f, 0.0f, 1.0f); for (i = 1; i < X_WIDTH; i++) { glVertex2i(x0Position + i, y0position); glVertex2i(x0Position + i, y0position - fs[i]); } glEnd(); } void dispr(int fr[], int x0Position, int y0position, int amplitude, int k) { int i; glColor4f(1.0f, 1.0f, 1.0f, 1.0f); Line2D(x0Position, y0position - amplitude, x0Position, y0position + amplitude, 1.0); Line2D(x0Position, y0position, x0Position + X_WIDTH, y0position, 1.0); glVertex2i(x0Position + k, y0position - fr[k]); glLineWidth(1); glBegin(GL_POINTS); glColor4f(0.0f, 1.0f, 0.0f, 1.0f); for (i = k; i < X_WIDTH - k; i++) { glVertex2i(x0Position + i, y0position - fr[i]); } glEnd(); }
実行サンプル
課題
(注意)
Cygwinなどでglutを使っている場合には,GL/freeglut.h をGL/glut.hに変える.
makeファイルについては,glutをつかったプログラムに適したものを使うこと.
プログラム中の「<,>」が全角になっているので,それを半角に置換する.
(1)ナイキストの標本化定理
ナイキストの標本化定理が成り立つことを実験で確かめよ. 確かめたときに用いた,「原波形の周期」と「サンプリング間隔」の値と,「サンプリング開始までの待ち時間」 その時の様子を提示する. 確かめるには,少なくとも2件以上の条件で様子を観察する必要があるだろう.
(2)エイリアシングエイリアシングが発生することを確かめよ. エイリアシングが発生するときの,「原波形の周期」と「サンプリング間隔」の値,「サンプリング開始までの待ち時間」とその時の様子を提示する.
提出方法
締切日時:4月17日
提出先:印刷したものを授業前に提出する
題名:ディジタル信号処理(サンプリング)
提出物:課題に対する問題文と解答を示した印刷物
章立てなどをする必要はない.問いに対する解答が十分に示されていればよい.