周波数領域での信号処理


 サンプルプログラム Sample2.lzh を参考に、 周波数領域で信号処理 を行います。 このプログラムは、 入力信号を高速フーリエ変換 (FFT) して周波数領域に変換し、 低周波成分だけを逆FFTして時間領域に戻し、出力します。 サンプリング周波数は48kHz (これは固定)、 入力チャンネル数は2チャンネル、 出力チャンネル数は2チャンネル、 FFT点数は512となっています。 入出力チャンネル数とFFT点数は「tt.h」で定義されています。

 実際に信号処理を行っている部分は「ProcessInput.c」です。 内容は、

  1. グローバル変数を定義
  2. 関数「Init()」を定義
    FFT用のsin/cosテーブルを作成
  3. 関数「ProcessInput()」を定義
    1. フーリエ変換
    2. 周波数が「FFT_SIZE / 64」未満の成分をコピー
      正と負の周波数成分両方を処理する。
    3. 逆フーリエ変換
となっています。 低域通過フィルタ (LPF) として動作します。 入出力チャンネルは、
// List of input/output channel indices
int buf_in_channels[FFT_IN_CHANNELS] = {0, 1};          // List of input channel indices
int buf_out_channels[FFT_OUT_CHANNELS] = {6, 7};        // List of output channel indices
で指定しています。 入力はアナログ入力、 出力はCH4とヘッドホンになっています。 ディジタル入力を使用する場合には、
// List of input/output channel indices
int buf_in_channels[FFT_IN_CHANNELS] = {2, 3};          // List of input channel indices
としてください。

 このプログラムを改造してみましょう。


 「ProcessInput.c」は以下の通りのプログラムです。

////////////////////////////////////////////////////////////////////////////////////////
//
//FFT-based talkthrough
//
//Original program "blockProcess.c" from Ez-Kit Lite example
//Modifided by Akihiro HIRANO <hirano@t.kanazawa-u.ac.jp>
//Last update: Apr 25, 2007
//
////////////////////////////////////////////////////////////////////////////////////////
#include "tt.h"

// Arrays for FFT
complex_float *fft_in_t[FFT_IN_CHANNELS];               // Time-domain input signals
complex_float fft_in_f[FFT_IN_CHANNELS][FFT_SIZE];      // Frequency-domain input signals
complex_float fft_out_f[FFT_OUT_CHANNELS][FFT_SIZE];    // Frequency-domain output signals
complex_float *fft_out_t[FFT_OUT_CHANNELS];             // Time-domain output signals
complex_float fft_temp[FFT_SIZE];                       // Temporary strage
complex_float pm fft_twiddle[FFT_SIZE / 2];             // sin/cos table

// List of input/output channel indices
int buf_in_channels[FFT_IN_CHANNELS] = {0, 1};          // List of input channel indices
int buf_out_channels[FFT_OUT_CHANNELS] = {6, 7};        // List of output channel indices

// Place the initialization code for the audio processing here.
void Init(void)
{
    twidfft(fft_twiddle, FFT_SIZE);
}

// Place the audio processing algorith here.
// The input and output are given as arrays of float.
void ProcessInput(void)
{
    static int count = 0;
    int ch, f;

    //Clear the Block Ready Semaphore
    //Do not modify.
    blockReady = 0;
    
    //Set the Processing Active Semaphore before starting processing
    //Do not modify
    isProcessing = 1;

    // Fourier Transform: Calculate frequecy components of input signals
    for (ch = 0; ch < FFT_IN_CHANNELS; ch++) {
        cfft(fft_in_t[ch], fft_temp, fft_in_f[ch], fft_twiddle, 1, FFT_SIZE);
    }

    //
    for (ch = 0; ch < FFT_IN_CHANNELS; ch++) {
        fft_out_f[ch][0].re = fft_in_f[ch][0].re;    // DC (f=0) components
        fft_out_f[ch][0].im = fft_in_f[ch][0].im;
        fft_out_f[ch][FFT_SIZE / 2].re = 0.0;        // fs/2 components: should be zero
        fft_out_f[ch][FFT_SIZE / 2].im = 0.0;
        for (f = 1; f < (FFT_SIZE / 2); f++) {
            if (f < FFT_SIZE / 64) {
                // +f components
                fft_out_f[ch][f].re = fft_in_f[ch][f].re;
                fft_out_f[ch][f].im = fft_in_f[ch][f].im;
                // -f components
                fft_out_f[ch][FFT_SIZE - f].re = fft_in_f[ch][FFT_SIZE - f].re;
                fft_out_f[ch][FFT_SIZE - f].im = fft_in_f[ch][FFT_SIZE - f].im;
            }
            else {
                // +f components
                fft_out_f[ch][f].re = 0.0;
                fft_out_f[ch][f].im = 0.0;
                // -f components
                fft_out_f[ch][FFT_SIZE - f].re = 0.0;
                fft_out_f[ch][FFT_SIZE - f].im = 0.0;
            }
        }
    }

    // Inverse Fourier Transform: Calculate time-domain components of output signals
    for (ch = 0; ch < FFT_OUT_CHANNELS; ch++) {
        ifft(fft_out_f[ch], fft_temp, fft_out_t[ch], fft_twiddle, 1, FFT_SIZE);
    }

    // Blink LED 1
    count++;
    if ((count & 0x0f) == 0) {
        if (count & 0x80) {
            OffLED(1);
        }
        else {
            OnLED(1);
        }
    }

    //Clear the Processing Active Semaphore after processing is complete
    //Do not modify
    isProcessing = 0;
}


[上へ] [戻る 信号発生器] [目次]