Main Page | Data Structures | Directories | File List | Data Fields | Globals

fft.hcc

Go to the documentation of this file.
00001 
00020 #include <stdlib.hch>
00021 #include "pal_master.hch"
00022 
00023 #include "audio.hch"
00024 #include "weights_256.hch"
00025 #include "configuration.hch"
00026 #include "xilinxmult.hch"
00027 #include "fft.hch"
00028 
00029 #if HAVE_DEBUG
00030         #include "debug.hch"
00031 #endif
00032 
00033 /* Define two multi-port RAMs for FFT calculation; one for real and one for imaginary values
00034  * Extra block RAM settings are defined to make sure read and write actions can be performed
00035  * within one clock-cycle.
00036  * Left out extra settings on new board the clock changes TODO !!!!
00037  */
00038 #if HARDWARE_MULTIPLY
00039 mpram
00040 {
00041   ram signed 18 rwrite[256];
00042   rom signed 18 read[256];
00043 } real with {block = "BlockRAM"/*, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/};
00044 
00045 mpram 
00046 {
00047   ram signed 18 rwrite[256];
00048   rom signed 18 read[256];
00049 } imaginary with {block = "BlockRAM"/*, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/};
00050 #else
00051 mpram
00052 {
00053   ram signed 24 rwrite[256];
00054   rom signed 24 read[256];
00055 } real with {block = "BlockRAM"/*, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/};
00056 
00057 mpram 
00058 {
00059   ram signed 24 rwrite[256];
00060   rom signed 24 read[256];
00061 } imaginary with {block = "BlockRAM"/*, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/};
00062 #endif
00063 // multiplication factors for equalizer function
00064 ram signed 7 eq_settings[16] = {0,2,4,7,10,13,16,19,22,26,30,35,41,48,55,63};
00065 
00066 #if HARDWARE_MULTIPLY
00067 #define DC_COMPONENT            0
00068 #else
00069 #define DC_COMPONENT            8470527
00070 #endif
00071 
00082 macro proc multiply(result, op_a, op_b)
00083 {
00084 #if HARDWARE_MULTIPLY
00085         xilinxmult(result, op_a, adjs(op_b,18));
00086 #else
00087         result = (adjs(op_a,38))*(adjs(op_a,38));
00088 #endif  
00089 }
00090 
00091 
00092 
00093 
00104 void calculate_fft(unsigned 1 select_inverse)
00105 {
00106   unsigned 4 level;
00107   unsigned 8 point1,point2,j,f,k;
00108   unsigned 9 e,i;
00109   signed 16 weight1,weight2;
00110 #if HARDWARE_MULTIPLY
00111   signed 18 p,q,r,t;
00112 #else
00113   signed 24 p,q,r,t;    
00114 #endif
00115   signed a,b;
00116 
00117 #if HARDWARE_MULTIPLY
00118   // Macro to provide rescaling of 36-bit result of fixed point multiply
00119   // down to an 18-bit result. The range of bits selected depends on the 
00120   // number that represents the value of "1" in the trig function lookup
00121   // tables. (Eg. for 16384 == 1, the lowest bit selected should be [14]).
00122   macro expr rescale (x) = (x[35] @ x[30:14]);
00123 #else
00124   //Macro to rescale the multiply result down to a 24-bit value.
00125   macro expr rescale (x) = ((x>>FRACBITS)<-24);
00126 #endif
00127 
00128   for(level=1;level<=NUMBER_OF_COLUMNS;level++) // count all the columns
00129   {
00130         e=1<<(NUMBER_OF_COLUMNS-level+1); // number of points in each block in this column
00131         f=(e>>1)<-8;                      // number of butterflies in each block in this column
00132 
00133         for(j=1;j<=f;j++)       // count all the butterflies in each block
00134         {
00135                 par
00136                 {
00137                         // Weight factors for real (the same for FFT and iFFT)
00138                         weight1 = weight_re[((j-1)<<(level-1))<-7]; 
00139 
00140                         
00141                         // Weight factors for imaginary (opposite for FFT and iFFT)
00142                         weight2 = (!select_inverse) ? (weight_im[((j-1)<<(level-1))<-7]) : -(weight_im[((j-1)<<(level-1))<-7]); 
00143 
00144                         /* ORIGINAL CODE BELOW, MODIFIED BECAUSE OF MISMATCHING OUTPUT WITH BORLAND TESTAPP
00145                         weight2 = (!select_inverse) ? -(weight_im[((j-1)<<(level-1))<-7]) : weight_im[((j-1)<<(level-1))<-7]; 
00146                         */
00147                         
00148                         
00149 
00150                         for(i=0@j;i<=NUMBER_OF_POINTS;i+=e)   // count all the blocks in this column
00151                         {       // Butterfly calculation
00152                                 par
00153                                 {
00154                                         point1 = ((i<-8)-1);
00155                                         point2 = (((i<-8)+f)-1);
00156                                 }
00157                                 
00158                                 par
00159                                 {
00160                                         p = (real.read[point1] >> 1) + (real.rwrite[point2] >> 1);
00161                                         q = (imaginary.read[point1] >> 1) + (imaginary.rwrite[point2] >> 1);
00162                                 }
00163                                 
00164                                 par
00165                                 {
00166                                         r = (real.read[point1] >> 1) - (real.rwrite[point2] >> 1);
00167                                         t = (imaginary.read[point1] >> 1) - (imaginary.rwrite[point2] >> 1);
00168                                 }               
00169 
00170                                 multiply(a,r,weight1);
00171                                 multiply(b,t,weight2);
00172 
00173                                 par
00174                                 {
00175                                         real.rwrite[point2] = (rescale(a-b));
00176                                         imaginary.rwrite[point1] = q;
00177                                 }
00178 
00179                                 multiply(a,t,weight1);
00180                                 multiply(b,r,weight2);
00181 
00182                                 par
00183                                 {       
00184                                         real.rwrite[point1] = p;
00185                                         imaginary.rwrite[point2] = (rescale(a+b));
00186                                 }
00187 
00188                         }
00189                 }
00190         }
00191   }
00192 
00193   j=1;
00194   for(i=1;i<NUMBER_OF_POINTS;i++)
00195   {
00196         if(i<(0@j))
00197         {
00198                 par
00199                 {
00200                         point1=j-1;
00201                         point2=(i-1)<-8;
00202                 }
00203                 /*
00204                   COPYING ARRAY VALUES FROM ONE PLACE TO ANOTHER IN THE ARRAT MUST BE DONE IN 
00205                   2 STEPS. FIRSTLY THE VALUES ARE COPIED TO SEPARATE VARIABLES AFTER THAT THEY
00206                   ARE COPIED BACK TO THEIR NEW POSITION IN THE ARRAY. THIS MUST BE DONE TO 
00207                   PREVENT TIMING ISSUES FROM OCCURING.
00208                 */
00209                 par
00210                 {
00211                         p = real.read[point1];
00212                         q = imaginary.read[point1];
00213                 }
00214                 par
00215                 {
00216                         r = real.read[point2];
00217                         t = imaginary.read[point2];
00218                 }
00219                 par
00220                 {
00221                         real.rwrite[point1] = r;        
00222                         imaginary.rwrite[point1] = t;
00223                 }
00224                 par
00225                 {
00226                         real.rwrite[point2] = p;
00227                         imaginary.rwrite[point2] = q;
00228                 }
00229         }
00230 
00231         k = NUMBER_OF_POINTS>>1;
00232 
00233 
00234         while(k<j)
00235         {
00236                 j = j-k;
00237                 k = k>>1;
00238         }
00239 
00240         j+=k;
00241   }
00242 
00243 }
00244 
00256 #if HARDWARE_MULTIPLY
00257 void perform_fft(signed 18 *pcm_audio)
00258 #else
00259 void perform_fft(signed 16 *pcm_audio)
00260 #endif
00261 {
00262         unsigned 8 k;
00263 #if HARDWARE_MULTIPLY
00264         signed 18 sample;
00265         k=0;
00266         sample = adjs(pcm_audio[k],18);
00267 #else
00268         signed 24 sample;
00269         k=0;
00270         sample = adjs(pcm_audio[k],24);
00271 #endif
00272         
00273         //initialize variables for the copying pipeline
00274 
00275         
00276         // copy audio data to real-array before starting FFT calculation
00277         // and set imaginary values to zero
00278         do
00279         {
00280                 //Copying the array values has been pipelined to prevent parallel access to the
00281                 //pcm_audio array. This copying procedure must be finished before another 
00282                 //sample is read from the audio input. The time available for this loop is 
00283                 //determined by the sampling rate of 44,1 Khz
00284                 par
00285                 {
00286                         //COPYING NEEDS TO BE DONE IN 2 STEPS, BECAUSE THE VALUE THAT NEEDS TO WRITTEN
00287                         //TO THE REAL-RAM NEEDS TO BE AVAILABLE ON THE START OFF THE CLOCKCYCLE.
00288 #if HARDWARE_MULTIPLY
00289                         sample = adjs(pcm_audio[k+1],18);
00290 #else
00291                         sample = adjs(pcm_audio[k+1],24);
00292 #endif
00293                         real.rwrite[k] = sample;
00294                         imaginary.rwrite[k] = 0;
00295                         k++;
00296                 }               
00297         }  while (k);
00298 
00299         
00300 
00301 #if PERFORM_FFT_CALCULATION
00302         calculate_fft(0);
00303 #endif
00304 
00305 
00306 }
00307 
00321 #if HARDWARE_MULTIPLY
00322 void perform_ifft(signed 18 *modified_audio, unsigned 6 *ifft_info)
00323 #else
00324 void perform_ifft(signed 16 *modified_audio, unsigned 6 *ifft_info)
00325 #endif
00326 {
00327         unsigned 6 k;
00328 #if HARDWARE_MULTIPLY 
00329         signed 18 p;
00330 #else
00331         signed 24 p;
00332 #endif
00333 #if PERFORM_FFT_CALCULATION     
00334         calculate_fft(1);
00335 #endif
00336 
00337         k=0;
00338 //initialize variables for the copying pipeline
00339 #if PERFORM_FFT_CALCULATION     
00340         #if HARDWARE_MULTIPLY 
00341                 p = (real.read[(0@k)+95] << NUMBER_OF_COLUMNS);
00342         #else
00343                 p = (real.read[(0@k)+95] >> NUMBER_OF_COLUMNS);
00344         #endif
00345 #else
00346                 p = (real.read[(0@k)+95]);
00347 #endif
00348 
00349         do
00350         {
00351                 //Copying the array values has been pipelined to prevent parallel access to the
00352                 //pcm_audio array. This copying procedure must be finished before another 
00353                 //sample is read from the audio input. The time available for this loop is 
00354                 //determined by the sampling rate of 44,1 Khz
00355                 par
00356                 {
00357                         /*
00358                         *       Before copying the modified audio from the local real-array 
00359                         *       to the output array of the audio I/O component, compensate
00360                         *       for the FFT calculation by shifting the values. 
00361                         *       95 is added to start the output from the middle of the sliding
00362                         *       window, this is done to get a better sound quality.
00363                         */
00364 #if PERFORM_FFT_CALCULATION     
00365         #if HARDWARE_MULTIPLY 
00366                         p = (real.read[(0@k)+95] << NUMBER_OF_COLUMNS);
00367         #else
00368                         p = (real.read[(0@k)+95] >> NUMBER_OF_COLUMNS);
00369         #endif
00370 #else
00371                         p = (real.read[(0@k)+95]);
00372 #endif
00373                         //Copy the modified audio from the local real array to the output array of the audio I/O component.
00374 #if HARDWARE_MULTIPLY
00375                         modified_audio[k] = p ;
00376 #else
00377                         modified_audio[k] = (p<-16);
00378 #endif
00379                         //Fill the array for displaying the waveform, only the 6 MSB are needed.
00380                         ifft_info[k] = (unsigned 6)(32+(p[17:12]));             
00381                         k++;
00382                 }
00383         } while(k);
00384 }
00385 
00398 void equalize_audio(audiodata_t *audiodata)
00399 {
00400 #if HARDWARE_MULTIPLY
00401   signed 18 p,q;
00402 #else
00403   signed 24 p,q;
00404 #endif
00405   signed 18 a;
00406   unsigned 8 i, mirror_i, bit, m, n;
00407   unsigned 7 old_value;
00408   unsigned 9 tmp;
00409   
00410   //macro expr equalize_bar = multiply(q,a)[29:6];
00411   
00412   macro proc equalize_bar(retval)
00413   {
00414          signed result;
00415          multiply(result, q,a);
00416 #if HARDWARE_MULTIPLY
00417          retval = result[23:6]; //drop last 6 bit to compensate the maximum multiplication with 64 from the eq_settings array
00418 #else
00419          retval = result[29:6]; //drop last 6 bit to compensate the maximum multiplication with 64 from the eq_settings array
00420 #endif
00421   } 
00422 
00423   p = real.read[0] - DC_COMPONENT; // remove DC component for calculations
00424   real.rwrite[0] = p;
00425   
00426   for(i=0;i!=NUMBER_OF_FREQUENCIES;i++)   
00427   {  
00428         
00429                 // set multiplication factor (0..64) for current frequency bar, The first frequency band must be equalized at 100% (63) since there is no DC-component taken into account.
00430                 a = adjs(eq_settings[audiodata->equalizer_levels_ptr[i <- 7]],18);
00431 
00432 
00433                 // multiply frequency with this factor and divide by 64 (drop 6 LSB's)
00434                 q = real.read[i];
00435         equalize_bar(p);
00436         real.rwrite[i] = p;
00437 
00438         q = imaginary.read[i];
00439         equalize_bar(p);
00440         imaginary.rwrite[i] = p;
00441 
00442         // the upper part(128..255) of the spectrum is mirrored to the lower part; 
00443         // these values need to be adjusted too
00444         if ((i<-7)!=0) // if not in DC component bar
00445         {
00446                 mirror_i = (NUMBER_OF_POINTS-1)-i+1;
00447                 q = real.read[mirror_i];
00448                 equalize_bar(p);
00449                 real.rwrite[mirror_i] = p;
00450 
00451                 q = imaginary.read[mirror_i];
00452                 equalize_bar(p);
00453                 imaginary.rwrite[mirror_i] = p;
00454         }
00455   }
00456   
00457   //write data to fft_info for display purposes
00458   for(i=0;i<NUMBER_OF_FREQUENCIES;i++)
00459   {
00460                 p = real.read[i];
00461                 q = imaginary.read[i];
00462 #if HARDWARE_MULTIPLY
00463                 if (p[17] == 1) p = -p; else delay;
00464                 if (q[17] == 1) q = -q; else delay;
00465 #else
00466                 if (p[23] == 1) p = -p; else delay;
00467                 if (q[23] == 1) q = -q; else delay;
00468 #endif
00469         p = (p<q) ? q : p; // This is done to get the best visual frequency result
00470          
00471         if (!audiodata->display_log)
00472         {
00473 
00474                 bit=126;
00475 #if HARDWARE_MULTIPLY
00476                 while ((p[15] == 0) && (bit != 0))
00477 #else
00478                 while ((p[21] == 0) && (bit != 0))
00479 #endif
00480                         par
00481                         {
00482                                 p = p<<1;
00483                                 bit = bit - 18;
00484                         }
00485                 old_value = audiodata->fft_info.write[0 @ (i <- 7)];
00486                 tmp = ((0@old_value) + (0@bit))>>1;
00487                 audiodata->fft_info.write[0 @ (i <- 7)] = (old_value <= (tmp<-7)) ? (tmp<-7) : old_value-1;
00488         } 
00489         else 
00490         {
00491                 old_value = audiodata->fft_info.write[0 @ (i <- 7)];
00492 #if HARDWARE_MULTIPLY
00493                 audiodata->fft_info.write[0 @ (i <- 7)] = (old_value<=(unsigned)(p[15:9])) ? (unsigned)(p[15:9]) : old_value-1;
00494 #else
00495                 audiodata->fft_info.write[0 @ (i <- 7)] = (old_value<=(unsigned)(p[21:15])) ? (unsigned)(p[21:15]) : old_value-1;
00496 #endif
00497         }
00498   }
00499 
00500   // add DC component again before inverse FFT calculation is performed
00501 
00502   p = real.read[0] + DC_COMPONENT; 
00503   real.rwrite[0] = p;
00504 }
00505 

Generated on Thu Dec 9 14:37:07 2004 for Graphic Equalizer 2 by  doxygen 1.3.9.1