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