You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

295 lines
6.6KB

  1. /* FFT and MDCT tests */
  2. #include "dsputil.h"
  3. #include <math.h>
  4. #include <getopt.h>
  5. #include <sys/time.h>
  6. int mm_flags;
  7. void *av_malloc(int size)
  8. {
  9. void *ptr;
  10. ptr = malloc(size);
  11. return ptr;
  12. }
  13. void av_free(void *ptr)
  14. {
  15. /* XXX: this test should not be needed on most libcs */
  16. if (ptr)
  17. free(ptr);
  18. }
  19. /* cannot call it directly because of 'void **' casting is not automatic */
  20. void __av_freep(void **ptr)
  21. {
  22. av_free(*ptr);
  23. *ptr = NULL;
  24. }
  25. /* reference fft */
  26. #define MUL16(a,b) ((a) * (b))
  27. #define CMAC(pre, pim, are, aim, bre, bim) \
  28. {\
  29. pre += (MUL16(are, bre) - MUL16(aim, bim));\
  30. pim += (MUL16(are, bim) + MUL16(bre, aim));\
  31. }
  32. FFTComplex *exptab;
  33. void fft_ref_init(int nbits, int inverse)
  34. {
  35. int n, i;
  36. float c1, s1, alpha;
  37. n = 1 << nbits;
  38. exptab = av_malloc((n / 2) * sizeof(FFTComplex));
  39. for(i=0;i<(n/2);i++) {
  40. alpha = 2 * M_PI * (float)i / (float)n;
  41. c1 = cos(alpha);
  42. s1 = sin(alpha);
  43. if (!inverse)
  44. s1 = -s1;
  45. exptab[i].re = c1;
  46. exptab[i].im = s1;
  47. }
  48. }
  49. void fft_ref(FFTComplex *tabr, FFTComplex *tab, int nbits)
  50. {
  51. int n, i, j, k, n2;
  52. float tmp_re, tmp_im, s, c;
  53. FFTComplex *q;
  54. n = 1 << nbits;
  55. n2 = n >> 1;
  56. for(i=0;i<n;i++) {
  57. tmp_re = 0;
  58. tmp_im = 0;
  59. q = tab;
  60. for(j=0;j<n;j++) {
  61. k = (i * j) & (n - 1);
  62. if (k >= n2) {
  63. c = -exptab[k - n2].re;
  64. s = -exptab[k - n2].im;
  65. } else {
  66. c = exptab[k].re;
  67. s = exptab[k].im;
  68. }
  69. CMAC(tmp_re, tmp_im, c, s, q->re, q->im);
  70. q++;
  71. }
  72. tabr[i].re = tmp_re;
  73. tabr[i].im = tmp_im;
  74. }
  75. }
  76. void imdct_ref(float *out, float *in, int n)
  77. {
  78. int k, i, a;
  79. float sum, f;
  80. for(i=0;i<n;i++) {
  81. sum = 0;
  82. for(k=0;k<n/2;k++) {
  83. a = (2 * i + 1 + (n / 2)) * (2 * k + 1);
  84. f = cos(M_PI * a / (double)(2 * n));
  85. sum += f * in[k];
  86. }
  87. out[i] = -sum;
  88. }
  89. }
  90. /* NOTE: no normalisation by 1 / N is done */
  91. void mdct_ref(float *output, float *input, int n)
  92. {
  93. int k, i;
  94. float a, s;
  95. /* do it by hand */
  96. for(k=0;k<n/2;k++) {
  97. s = 0;
  98. for(i=0;i<n;i++) {
  99. a = (2*M_PI*(2*i+1+n/2)*(2*k+1) / (4 * n));
  100. s += input[i] * cos(a);
  101. }
  102. output[k] = s;
  103. }
  104. }
  105. float frandom(void)
  106. {
  107. return (float)((random() & 0xffff) - 32768) / 32768.0;
  108. }
  109. INT64 gettime(void)
  110. {
  111. struct timeval tv;
  112. gettimeofday(&tv,NULL);
  113. return (INT64)tv.tv_sec * 1000000 + tv.tv_usec;
  114. }
  115. void check_diff(float *tab1, float *tab2, int n)
  116. {
  117. int i;
  118. for(i=0;i<n;i++) {
  119. if (fabsf(tab1[i] - tab2[i]) >= 1e-3) {
  120. printf("ERROR %d: %f %f\n",
  121. i, tab1[i], tab2[i]);
  122. }
  123. }
  124. }
  125. void help(void)
  126. {
  127. printf("usage: fft-test [-h] [-s] [-i] [-n b]\n"
  128. "-h print this help\n"
  129. "-s speed test\n"
  130. "-m (I)MDCT test\n"
  131. "-i inverse transform test\n"
  132. "-n b set the transform size to 2^b\n"
  133. );
  134. exit(1);
  135. }
  136. int main(int argc, char **argv)
  137. {
  138. FFTComplex *tab, *tab1, *tab_ref;
  139. FFTSample *tabtmp, *tab2;
  140. int it, i, c;
  141. int do_speed = 0;
  142. int do_mdct = 0;
  143. int do_inverse = 0;
  144. FFTContext s1, *s = &s1;
  145. MDCTContext m1, *m = &m1;
  146. int fft_nbits, fft_size;
  147. mm_flags = 0;
  148. fft_nbits = 9;
  149. for(;;) {
  150. c = getopt(argc, argv, "hsimn:");
  151. if (c == -1)
  152. break;
  153. switch(c) {
  154. case 'h':
  155. help();
  156. break;
  157. case 's':
  158. do_speed = 1;
  159. break;
  160. case 'i':
  161. do_inverse = 1;
  162. break;
  163. case 'm':
  164. do_mdct = 1;
  165. break;
  166. case 'n':
  167. fft_nbits = atoi(optarg);
  168. break;
  169. }
  170. }
  171. fft_size = 1 << fft_nbits;
  172. tab = av_malloc(fft_size * sizeof(FFTComplex));
  173. tab1 = av_malloc(fft_size * sizeof(FFTComplex));
  174. tab_ref = av_malloc(fft_size * sizeof(FFTComplex));
  175. tabtmp = av_malloc(fft_size / 2 * sizeof(FFTSample));
  176. tab2 = av_malloc(fft_size * sizeof(FFTSample));
  177. if (do_mdct) {
  178. if (do_inverse)
  179. printf("IMDCT");
  180. else
  181. printf("MDCT");
  182. mdct_init(m, fft_nbits, do_inverse);
  183. } else {
  184. if (do_inverse)
  185. printf("IFFT");
  186. else
  187. printf("FFT");
  188. fft_init(s, fft_nbits, do_inverse);
  189. fft_ref_init(fft_nbits, do_inverse);
  190. }
  191. printf(" %d test\n", fft_size);
  192. /* generate random data */
  193. for(i=0;i<fft_size;i++) {
  194. tab1[i].re = frandom();
  195. tab1[i].im = frandom();
  196. }
  197. /* checking result */
  198. printf("Checking...\n");
  199. if (do_mdct) {
  200. if (do_inverse) {
  201. imdct_ref((float *)tab_ref, (float *)tab1, fft_size);
  202. imdct_calc(m, tab2, (float *)tab1, tabtmp);
  203. check_diff((float *)tab_ref, tab2, fft_size);
  204. } else {
  205. mdct_ref((float *)tab_ref, (float *)tab1, fft_size);
  206. mdct_calc(m, tab2, (float *)tab1, tabtmp);
  207. check_diff((float *)tab_ref, tab2, fft_size / 2);
  208. }
  209. } else {
  210. memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
  211. fft_permute(s, tab);
  212. fft_calc(s, tab);
  213. fft_ref(tab_ref, tab1, fft_nbits);
  214. check_diff((float *)tab_ref, (float *)tab, fft_size * 2);
  215. }
  216. /* do a speed test */
  217. if (do_speed) {
  218. INT64 time_start, duration;
  219. int nb_its;
  220. printf("Speed test...\n");
  221. /* we measure during about 1 seconds */
  222. nb_its = 1;
  223. for(;;) {
  224. time_start = gettime();
  225. for(it=0;it<nb_its;it++) {
  226. if (do_mdct) {
  227. if (do_inverse) {
  228. imdct_calc(m, (float *)tab, (float *)tab1, tabtmp);
  229. } else {
  230. mdct_calc(m, (float *)tab, (float *)tab1, tabtmp);
  231. }
  232. } else {
  233. memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
  234. fft_calc(s, tab);
  235. }
  236. }
  237. duration = gettime() - time_start;
  238. if (duration >= 1000000)
  239. break;
  240. nb_its *= 2;
  241. }
  242. printf("time: %0.1f us/transform [total time=%0.2f s its=%d]\n",
  243. (double)duration / nb_its,
  244. (double)duration / 1000000.0,
  245. nb_its);
  246. }
  247. if (do_mdct) {
  248. mdct_end(m);
  249. } else {
  250. fft_end(s);
  251. }
  252. return 0;
  253. }