サンプリングと復元

#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日
提出先:印刷したものを授業前に提出する
題名:ディジタル信号処理(サンプリング)
提出物:課題に対する問題文と解答を示した印刷物
章立てなどをする必要はない.問いに対する解答が十分に示されていればよい.

サンプリングと復元