サンプルプログラム 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; }